1 // Copyright (c) 2005 by Leif Frenzel. All rights reserved.
2 // See http://leiffrenzel.de
3 // modified for phpeclipse.de project by axelcl
4 package net.sourceforge.phpdt.ltk.core;
6 import java.io.ByteArrayOutputStream;
7 import java.io.InputStream;
8 import java.util.ArrayList;
10 import net.sourceforge.phpdt.core.ISourceRange;
11 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
12 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
13 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
14 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
15 import net.sourceforge.phpdt.internal.core.SourceMethod;
16 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IProject;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24 import org.eclipse.ltk.core.refactoring.CompositeChange;
25 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
26 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
27 import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
28 import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
32 * delegate object that contains the logic used by the processor.
36 public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
38 public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
42 RefactoringStatus checkInitialConditions() {
43 RefactoringStatus result = new RefactoringStatus();
44 IFile sourceFile = info.getSourceFile();
45 if (sourceFile == null || !sourceFile.exists()) {
46 result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
47 } else if (info.getSourceFile().isReadOnly()) {
48 result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
49 } else if (isEmpty(info.getOldName())) {
50 // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
51 result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
56 RefactoringStatus checkFinalConditions(final IProgressMonitor pm,
57 final CheckConditionsContext ctxt) {
58 RefactoringStatus result = new RefactoringStatus();
59 pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
60 // do something long-running here: traverse the entire project (or even
61 // workspace) to look for all *.p files with the same bundle
63 IFile file = info.getSourceFile();
64 IProject project = file.getProject();
66 SourceMethod method = info.getMethod();
67 ISourceRange range = method.getSourceRange();
68 if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
69 determineMethodOffsets(file, range.getOffset(), range
70 .getLength(), result);
72 } catch (CoreException e) {
73 String msg = "Project: " + project.getFullPath().toOSString()
74 + " CoreException " + e.getMessage();
76 } catch (Exception e) {
77 String msg = "Project: " + project.getFullPath().toOSString()
78 + " Exception " + e.getMessage();
85 IFile[] files = new IFile[phpFiles.size()];
86 phpFiles.keySet().toArray(files);
87 IConditionChecker checker = ctxt
88 .getChecker(ValidateEditChecker.class);
89 ValidateEditChecker editChecker = (ValidateEditChecker) checker;
90 editChecker.addFiles(files);
96 protected void createChange(final IProgressMonitor pm,
97 final CompositeChange rootChange) {
99 pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges,
101 // all files in the same bundle
102 rootChange.addAll(createChangesForContainer(pm));
108 private void determineMethodOffsets(final IFile file, int offset,
109 int length, final RefactoringStatus status) {
110 ArrayList matches = new ArrayList();
112 String content = readFileContent(file, status);
115 // Find a PHPdoc directly before the method
117 Scanner firstScanner = new Scanner(true, false);
118 firstScanner.setSource(content.toCharArray());
119 int fToken = ITerminalSymbols.TokenNameEOF;
121 int phpdocStart = -1;
123 fToken = firstScanner.getNextToken();
124 while (fToken != ITerminalSymbols.TokenNameEOF
126 if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC) {
127 phpdocStart = firstScanner
128 .getCurrentTokenStartPosition();
132 fToken = firstScanner.getNextToken();
133 start = firstScanner.getCurrentTokenStartPosition();
136 } catch (InvalidInputException e) {
137 String msg = "File: " + file.getFullPath().toOSString()
138 + " InvalidInputException " + e.getMessage();
139 status.addError(msg);
140 } catch (SyntaxError e) {
141 String msg = "File: " + file.getFullPath().toOSString()
142 + " SyntaxError " + e.getMessage();
143 status.addError(msg);
147 // Find matches for the word in the PHPdoc+method declaration
149 if (phpdocStart >= 0 && phpdocStart < offset) {
150 length += offset - phpdocStart;
151 offset = phpdocStart;
153 String methodString = content.substring(offset, offset + length);
154 Scanner secondScanner = new Scanner(true, false);
155 secondScanner.setSource(methodString.toCharArray());
156 secondScanner.setPHPMode(true);
157 String wordStr = info.getOldName();
158 boolean renameDQString = info.isRenameDQString();
159 boolean renamePHPdoc = info.isRenamePHPdoc();
160 boolean renameOtherComments = info.isRenameOtherComments();
161 char[] word = wordStr.toCharArray();
163 fToken = ITerminalSymbols.TokenNameEOF;
164 // double quoted string
166 // double quoted string offset
170 fToken = secondScanner.getNextToken();
171 while (fToken != ITerminalSymbols.TokenNameEOF) {
172 if (fToken == ITerminalSymbols.TokenNameVariable) {
173 if (secondScanner.equalsCurrentTokenSource(word)) {
174 // the current variable token is equal to the given
176 matches.add(new Integer(secondScanner
177 .getCurrentTokenStartPosition()
180 } else if (fToken == ITerminalSymbols.TokenNameStringDoubleQuote
182 // determine the word in double quoted strings:
183 tokenString = new String(secondScanner
184 .getCurrentTokenSource());
185 tokenOffset = secondScanner
186 .getCurrentTokenStartPosition();
188 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
189 matches.add(new Integer(offset + tokenOffset
192 } else if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
194 tokenString = new String(secondScanner
195 .getCurrentTokenSource());
196 tokenOffset = secondScanner
197 .getCurrentTokenStartPosition();
199 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
200 matches.add(new Integer(offset + tokenOffset
203 } else if ((fToken == ITerminalSymbols.TokenNameCOMMENT_BLOCK || fToken == ITerminalSymbols.TokenNameCOMMENT_LINE)
204 && renameOtherComments) {
205 tokenString = new String(secondScanner
206 .getCurrentTokenSource());
207 tokenOffset = secondScanner
208 .getCurrentTokenStartPosition();
210 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
211 matches.add(new Integer(offset + tokenOffset
215 fToken = secondScanner.getNextToken();
218 } catch (InvalidInputException e) {
219 String msg = "File: " + file.getFullPath().toOSString()
220 + " InvalidInputException " + e.getMessage();
221 status.addError(msg);
222 } catch (SyntaxError e) {
223 String msg = "File: " + file.getFullPath().toOSString()
224 + " SyntaxError " + e.getMessage();
225 status.addError(msg);
228 } catch (Exception e) {
229 String msg = "File: " + file.getFullPath().toOSString()
230 + " Exception " + e.getMessage();
231 status.addError(msg);
233 if (matches.size() > 0) {
234 phpFiles.put(file, matches);
238 private String readFileContent(final IFile file,
239 final RefactoringStatus refStatus) {
240 String result = null;
242 InputStream is = file.getContents();
243 byte[] buf = new byte[1024];
244 ByteArrayOutputStream bos = new ByteArrayOutputStream();
245 int len = is.read(buf);
247 bos.write(buf, 0, len);
251 result = new String(bos.toByteArray());
252 } catch (Exception ex) {
253 String msg = ex.toString();
254 refStatus.addFatalError(msg);
255 String pluginId = PHPeclipsePlugin.getPluginId();
256 IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
257 PHPeclipsePlugin.getDefault().getLog().log(status);