fixed https://sourceforge.net/tracker/index.php?func=detail&aid=1431163&group_id...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / ltk / core / RenameLocalVariableDelegate.java
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;
5
6 import java.io.ByteArrayOutputStream;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9
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;
17
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;
29
30 /**
31  * <p>
32  * delegate object that contains the logic used by the processor.
33  * </p>
34  *
35  */
36 public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
37
38   public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
39         super(info);
40   }
41
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);
52         }
53         return result;
54   }
55
56   RefactoringStatus checkFinalConditions(final IProgressMonitor pm, final CheckConditionsContext ctxt) {
57         RefactoringStatus result = new RefactoringStatus();
58         pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
59         // do something long-running here: traverse the entire project (or even
60         // workspace) to look for all *.p files with the same bundle
61         // base name
62         IFile file = info.getSourceFile();
63         IProject project = file.getProject();
64         try {
65           SourceMethod method = info.getMethod();
66           ISourceRange range = method.getSourceRange();
67           if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
68                 determineMethodOffsets(file, range.getOffset(), range.getLength(), result);
69           }
70         } catch (CoreException e) {
71           String msg = "Project: " + project.getLocation().toOSString() + " CoreException " + e.getMessage();
72           result.addError(msg);
73         } catch (Exception e) {
74           String msg = "Project: " + project.getLocation().toOSString() + " Exception " + e.getMessage();
75           result.addError(msg);
76         }
77
78         pm.worked(50);
79
80         if (ctxt != null) {
81           IFile[] files = new IFile[phpFiles.size()];
82           phpFiles.keySet().toArray(files);
83           IConditionChecker checker = ctxt.getChecker(ValidateEditChecker.class);
84           ValidateEditChecker editChecker = (ValidateEditChecker) checker;
85           editChecker.addFiles(files);
86         }
87         pm.done();
88         return result;
89   }
90
91   protected void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
92         try {
93           pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges, 100);
94           // all files in the same bundle
95           rootChange.addAll(createChangesForContainer(pm));
96         } finally {
97           pm.done();
98         }
99   }
100
101   private void determineMethodOffsets(final IFile file, int offset, int length, final RefactoringStatus status) {
102         ArrayList matches = new ArrayList();
103         try {
104           String content = readFileContent(file, status);
105
106           //
107           // Find a PHPdoc directly before the method
108           //
109           Scanner firstScanner = new Scanner(true, false);
110           firstScanner.setSource(content.toCharArray());
111           int fToken = ITerminalSymbols.TokenNameEOF;
112           int start = 0;
113           int phpdocStart = -1;
114           try {
115                 fToken = firstScanner.getNextToken();
116                 while (fToken != ITerminalSymbols.TokenNameEOF && start < offset) {
117                   if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC) {
118                         phpdocStart = firstScanner.getCurrentTokenStartPosition();
119                   } else {
120                         phpdocStart = -1;
121                   }
122                   fToken = firstScanner.getNextToken();
123                   start = firstScanner.getCurrentTokenStartPosition();
124                 }
125
126           } catch (InvalidInputException e) {
127                 String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
128                 status.addError(msg);
129           } catch (SyntaxError e) {
130                 String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
131                 status.addError(msg);
132           }
133
134           //
135           // Find matches for the word in the PHPdoc+method declaration
136           //
137           if (phpdocStart >= 0 && phpdocStart < offset) {
138                 length += offset - phpdocStart;
139                 offset = phpdocStart;
140           }
141           String methodString = content.substring(offset, offset + length);
142           Scanner secondScanner = new Scanner(true, false);
143           secondScanner.setSource(methodString.toCharArray());
144           secondScanner.setPHPMode(true);
145           String wordStr = info.getOldName();
146           boolean renameDQString = info.isRenameDQString();
147           boolean renamePHPdoc = info.isRenamePHPdoc();
148           boolean renameOtherComments = info.isRenameOtherComments();
149           char[] word = wordStr.toCharArray();
150
151           fToken = ITerminalSymbols.TokenNameEOF;
152           // double quoted string
153           String tokenString;
154           // double quoted string offset
155           int tokenOffset;
156           int index;
157           try {
158                 fToken = secondScanner.getNextToken();
159                 while (fToken != ITerminalSymbols.TokenNameEOF) {
160                   if (fToken == ITerminalSymbols.TokenNameVariable) {
161                         if (secondScanner.equalsCurrentTokenSource(word)) {
162                           // the current variable token is equal to the given word
163                           matches.add(new Integer(secondScanner.getCurrentTokenStartPosition() + offset));
164                         }
165                   } else if (fToken == ITerminalSymbols.TokenNameStringDoubleQuote && renameDQString) {
166                         // determine the word in double quoted strings:
167                         tokenString = new String(secondScanner.getCurrentTokenSource());
168                         tokenOffset = secondScanner.getCurrentTokenStartPosition();
169                         index = -1;
170                         while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
171                           matches.add(new Integer(offset + tokenOffset + index));
172                         }
173                   } else if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC && renamePHPdoc) {
174                         tokenString = new String(secondScanner.getCurrentTokenSource());
175                         tokenOffset = secondScanner.getCurrentTokenStartPosition();
176                         index = -1;
177                         while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
178                           matches.add(new Integer(offset + tokenOffset + index));
179                         }
180                   } else if ( (fToken == ITerminalSymbols.TokenNameCOMMENT_BLOCK || fToken == ITerminalSymbols.TokenNameCOMMENT_LINE) && renameOtherComments) {
181                         tokenString = new String(secondScanner.getCurrentTokenSource());
182                         tokenOffset = secondScanner.getCurrentTokenStartPosition();
183                         index = -1;
184                         while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
185                           matches.add(new Integer(offset + tokenOffset + index));
186                         }
187                   }
188                   fToken = secondScanner.getNextToken();
189                 }
190
191           } catch (InvalidInputException e) {
192                 String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
193                 status.addError(msg);
194           } catch (SyntaxError e) {
195                 String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
196                 status.addError(msg);
197           }
198
199         } catch (Exception e) {
200           String msg = "File: " + file.getLocation().toOSString() + " Exception " + e.getMessage();
201           status.addError(msg);
202         }
203         if (matches.size() > 0) {
204           phpFiles.put(file, matches);
205         }
206   }
207
208   private String readFileContent(final IFile file, final RefactoringStatus refStatus) {
209         String result = null;
210         try {
211           InputStream is = file.getContents();
212           byte[] buf = new byte[1024];
213           ByteArrayOutputStream bos = new ByteArrayOutputStream();
214           int len = is.read(buf);
215           while (len > 0) {
216                 bos.write(buf, 0, len);
217                 len = is.read(buf);
218           }
219           is.close();
220           result = new String(bos.toByteArray());
221         } catch (Exception ex) {
222           String msg = ex.toString();
223           refStatus.addFatalError(msg);
224           String pluginId = PHPeclipsePlugin.getPluginId();
225           IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
226           PHPeclipsePlugin.getDefault().getLog().log(status);
227         }
228         return result;
229   }
230
231 }