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.ITerminalSymbols.TokenName;
13 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
14 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
15 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
16 import net.sourceforge.phpdt.internal.core.SourceMethod;
17 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import org.eclipse.core.resources.IFile;
20 import org.eclipse.core.resources.IProject;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.ltk.core.refactoring.CompositeChange;
26 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
27 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
28 import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
29 import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
33 * delegate object that contains the logic used by the processor.
37 public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
39 public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
43 RefactoringStatus checkInitialConditions() {
44 RefactoringStatus result = new RefactoringStatus();
45 IFile sourceFile = info.getSourceFile();
46 if (sourceFile == null || !sourceFile.exists()) {
47 result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
48 } else if (info.getSourceFile().isReadOnly()) {
49 result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
50 } else if (isEmpty(info.getOldName())) {
51 // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
52 result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
57 RefactoringStatus checkFinalConditions(final IProgressMonitor pm,
58 final CheckConditionsContext ctxt) {
59 RefactoringStatus result = new RefactoringStatus();
60 pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
61 // do something long-running here: traverse the entire project (or even
62 // workspace) to look for all *.p files with the same bundle
64 IFile file = info.getSourceFile();
65 IProject project = file.getProject();
67 SourceMethod method = info.getMethod();
68 ISourceRange range = method.getSourceRange();
69 if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
70 determineMethodOffsets(file, range.getOffset(), range
71 .getLength(), result);
73 } catch (CoreException e) {
74 String msg = "Project: " + project.getFullPath().toOSString()
75 + " CoreException " + e.getMessage();
77 } catch (Exception e) {
78 String msg = "Project: " + project.getFullPath().toOSString()
79 + " Exception " + e.getMessage();
86 IFile[] files = new IFile[phpFiles.size()];
87 phpFiles.keySet().toArray(files);
88 IConditionChecker checker = ctxt
89 .getChecker(ValidateEditChecker.class);
90 ValidateEditChecker editChecker = (ValidateEditChecker) checker;
91 editChecker.addFiles(files);
97 protected void createChange(final IProgressMonitor pm,
98 final CompositeChange rootChange) {
100 pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges,
102 // all files in the same bundle
103 rootChange.addAll(createChangesForContainer(pm));
109 private void determineMethodOffsets(final IFile file, int offset,
110 int length, final RefactoringStatus status) {
111 ArrayList matches = new ArrayList();
113 String content = readFileContent(file, status);
116 // Find a PHPdoc directly before the method
118 Scanner firstScanner = new Scanner(true, false);
119 firstScanner.setSource(content.toCharArray());
120 TokenName fToken = ITerminalSymbols.TokenName.EOF;
122 int phpdocStart = -1;
124 fToken = firstScanner.getNextToken();
125 while (fToken != ITerminalSymbols.TokenName.EOF
127 if (fToken == ITerminalSymbols.TokenName.COMMENT_PHPDOC) {
128 phpdocStart = firstScanner
129 .getCurrentTokenStartPosition();
133 fToken = firstScanner.getNextToken();
134 start = firstScanner.getCurrentTokenStartPosition();
137 } catch (InvalidInputException e) {
138 String msg = "File: " + file.getFullPath().toOSString()
139 + " InvalidInputException " + e.getMessage();
140 status.addError(msg);
141 } catch (SyntaxError e) {
142 String msg = "File: " + file.getFullPath().toOSString()
143 + " SyntaxError " + e.getMessage();
144 status.addError(msg);
148 // Find matches for the word in the PHPdoc+method declaration
150 if (phpdocStart >= 0 && phpdocStart < offset) {
151 length += offset - phpdocStart;
152 offset = phpdocStart;
154 String methodString = content.substring(offset, offset + length);
155 Scanner secondScanner = new Scanner(true, false);
156 secondScanner.setSource(methodString.toCharArray());
157 secondScanner.setPHPMode(true);
158 String wordStr = info.getOldName();
159 boolean renameDQString = info.isRenameDQString();
160 boolean renamePHPdoc = info.isRenamePHPdoc();
161 boolean renameOtherComments = info.isRenameOtherComments();
162 char[] word = wordStr.toCharArray();
164 fToken = ITerminalSymbols.TokenName.EOF;
165 // double quoted string
167 // double quoted string offset
171 fToken = secondScanner.getNextToken();
172 while (fToken != ITerminalSymbols.TokenName.EOF) {
173 if (fToken == ITerminalSymbols.TokenName.VARIABLE) {
174 if (secondScanner.equalsCurrentTokenSource(word)) {
175 // the current variable token is equal to the given
177 matches.add(new Integer(secondScanner
178 .getCurrentTokenStartPosition()
181 } else if (fToken == ITerminalSymbols.TokenName.STRINGDOUBLEQUOTE
183 // determine the word in double quoted strings:
184 tokenString = new String(secondScanner
185 .getCurrentTokenSource());
186 tokenOffset = secondScanner
187 .getCurrentTokenStartPosition();
189 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
190 matches.add(new Integer(offset + tokenOffset
193 } else if (fToken == ITerminalSymbols.TokenName.COMMENT_PHPDOC
195 tokenString = new String(secondScanner
196 .getCurrentTokenSource());
197 tokenOffset = secondScanner
198 .getCurrentTokenStartPosition();
200 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
201 matches.add(new Integer(offset + tokenOffset
204 } else if ((fToken == ITerminalSymbols.TokenName.COMMENT_BLOCK || fToken == ITerminalSymbols.TokenName.COMMENT_LINE)
205 && renameOtherComments) {
206 tokenString = new String(secondScanner
207 .getCurrentTokenSource());
208 tokenOffset = secondScanner
209 .getCurrentTokenStartPosition();
211 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
212 matches.add(new Integer(offset + tokenOffset
216 fToken = secondScanner.getNextToken();
219 } catch (InvalidInputException e) {
220 String msg = "File: " + file.getFullPath().toOSString()
221 + " InvalidInputException " + e.getMessage();
222 status.addError(msg);
223 } catch (SyntaxError e) {
224 String msg = "File: " + file.getFullPath().toOSString()
225 + " SyntaxError " + e.getMessage();
226 status.addError(msg);
229 } catch (Exception e) {
230 String msg = "File: " + file.getFullPath().toOSString()
231 + " Exception " + e.getMessage();
232 status.addError(msg);
234 if (matches.size() > 0) {
235 phpFiles.put(file, matches);
239 private String readFileContent(final IFile file,
240 final RefactoringStatus refStatus) {
241 String result = null;
243 InputStream is = file.getContents();
244 byte[] buf = new byte[1024];
245 ByteArrayOutputStream bos = new ByteArrayOutputStream();
246 int len = is.read(buf);
248 bos.write(buf, 0, len);
252 result = new String(bos.toByteArray());
253 } catch (Exception ex) {
254 String msg = ex.toString();
255 refStatus.addFatalError(msg);
256 String pluginId = PHPeclipsePlugin.getPluginId();
257 IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
258 PHPeclipsePlugin.getDefault().getLog().log(status);