3f2571f83052f30cf68f121ff3e582117cba115c
[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,
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
62                 // base name
63                 IFile file = info.getSourceFile();
64                 IProject project = file.getProject();
65                 try {
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);
71                         }
72                 } catch (CoreException e) {
73                         String msg = "Project: " + project.getFullPath().toOSString()
74                                         + " CoreException " + e.getMessage();
75                         result.addError(msg);
76                 } catch (Exception e) {
77                         String msg = "Project: " + project.getFullPath().toOSString()
78                                         + " Exception " + e.getMessage();
79                         result.addError(msg);
80                 }
81
82                 pm.worked(50);
83
84                 if (ctxt != null) {
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);
91                 }
92                 pm.done();
93                 return result;
94         }
95
96         protected void createChange(final IProgressMonitor pm,
97                         final CompositeChange rootChange) {
98                 try {
99                         pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges,
100                                         100);
101                         // all files in the same bundle
102                         rootChange.addAll(createChangesForContainer(pm));
103                 } finally {
104                         pm.done();
105                 }
106         }
107
108         private void determineMethodOffsets(final IFile file, int offset,
109                         int length, final RefactoringStatus status) {
110                 ArrayList matches = new ArrayList();
111                 try {
112                         String content = readFileContent(file, status);
113
114                         //
115                         // Find a PHPdoc directly before the method
116                         //
117                         Scanner firstScanner = new Scanner(true, false);
118                         firstScanner.setSource(content.toCharArray());
119                         int fToken = ITerminalSymbols.TokenNameEOF;
120                         int start = 0;
121                         int phpdocStart = -1;
122                         try {
123                                 fToken = firstScanner.getNextToken();
124                                 while (fToken != ITerminalSymbols.TokenNameEOF
125                                                 && start < offset) {
126                                         if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC) {
127                                                 phpdocStart = firstScanner
128                                                                 .getCurrentTokenStartPosition();
129                                         } else {
130                                                 phpdocStart = -1;
131                                         }
132                                         fToken = firstScanner.getNextToken();
133                                         start = firstScanner.getCurrentTokenStartPosition();
134                                 }
135
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);
144                         }
145
146                         //
147                         // Find matches for the word in the PHPdoc+method declaration
148                         //
149                         if (phpdocStart >= 0 && phpdocStart < offset) {
150                                 length += offset - phpdocStart;
151                                 offset = phpdocStart;
152                         }
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();
162
163                         fToken = ITerminalSymbols.TokenNameEOF;
164                         // double quoted string
165                         String tokenString;
166                         // double quoted string offset
167                         int tokenOffset;
168                         int index;
169                         try {
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
175                                                         // word
176                                                         matches.add(new Integer(secondScanner
177                                                                         .getCurrentTokenStartPosition()
178                                                                         + offset));
179                                                 }
180                                         } else if (fToken == ITerminalSymbols.TokenNameStringDoubleQuote
181                                                         && renameDQString) {
182                                                 // determine the word in double quoted strings:
183                                                 tokenString = new String(secondScanner
184                                                                 .getCurrentTokenSource());
185                                                 tokenOffset = secondScanner
186                                                                 .getCurrentTokenStartPosition();
187                                                 index = -1;
188                                                 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
189                                                         matches.add(new Integer(offset + tokenOffset
190                                                                         + index));
191                                                 }
192                                         } else if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
193                                                         && renamePHPdoc) {
194                                                 tokenString = new String(secondScanner
195                                                                 .getCurrentTokenSource());
196                                                 tokenOffset = secondScanner
197                                                                 .getCurrentTokenStartPosition();
198                                                 index = -1;
199                                                 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
200                                                         matches.add(new Integer(offset + tokenOffset
201                                                                         + index));
202                                                 }
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();
209                                                 index = -1;
210                                                 while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
211                                                         matches.add(new Integer(offset + tokenOffset
212                                                                         + index));
213                                                 }
214                                         }
215                                         fToken = secondScanner.getNextToken();
216                                 }
217
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);
226                         }
227
228                 } catch (Exception e) {
229                         String msg = "File: " + file.getFullPath().toOSString()
230                                         + " Exception " + e.getMessage();
231                         status.addError(msg);
232                 }
233                 if (matches.size() > 0) {
234                         phpFiles.put(file, matches);
235                 }
236         }
237
238         private String readFileContent(final IFile file,
239                         final RefactoringStatus refStatus) {
240                 String result = null;
241                 try {
242                         InputStream is = file.getContents();
243                         byte[] buf = new byte[1024];
244                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
245                         int len = is.read(buf);
246                         while (len > 0) {
247                                 bos.write(buf, 0, len);
248                                 len = is.read(buf);
249                         }
250                         is.close();
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);
258                 }
259                 return result;
260         }
261
262 }