dfa9ce130a52615f8f676245b4895db752448e0a
[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         // finds the offsets of the identifier to rename
102         // usually, this would be the job of a proper parser;
103         // using a primitive brute-force approach here
104         private void determineMethodOffsets(final IFile file, int offset, int length, final RefactoringStatus status) {
105                 ArrayList matches = new ArrayList();
106                 try {
107                         String content = readFileContent(file, status);
108                         String methodString = content.substring(offset, offset + length);
109                         Scanner scanner = new Scanner(true, false);
110                         scanner.setSource(methodString.toCharArray());
111                         scanner.setPHPMode(true);
112                         String wordStr = info.getOldName();
113                         char[] word = wordStr.toCharArray();
114
115                         int fToken = ITerminalSymbols.TokenNameEOF;
116                         String dqStr;
117                         int dqOffset;
118                         int index;
119                         try {
120                                 fToken = scanner.getNextToken();
121                                 while (fToken != ITerminalSymbols.TokenNameEOF) {
122                                         if (fToken == ITerminalSymbols.TokenNameVariable) {
123                                                 if (scanner.equalsCurrentTokenSource(word)) {
124                                                         // the current variable token is equal to the given word
125                                                         matches.add(Integer.valueOf(scanner.getCurrentTokenStartPosition() + offset));
126                                                 }
127                                         } else if (fToken == ITerminalSymbols.TokenNameStringDoubleQuote) {
128                                                 // determine the word in double quoted strings:
129                                                 dqStr = new String(scanner.getCurrentTokenSource());
130                                                 dqOffset = scanner.getCurrentTokenStartPosition();
131                                                 index = -1;
132                                                 while ((index = dqStr.indexOf(wordStr, index + 1)) >= 0) {
133                                                         matches.add(Integer.valueOf(offset + dqOffset + index));
134                                                 }
135                                         }
136                                         fToken = scanner.getNextToken();
137                                 }
138
139                         } catch (InvalidInputException e) {
140                                 String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
141                                 status.addError(msg);
142                         } catch (SyntaxError e) {
143                                 String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
144                                 status.addError(msg);
145                         }
146
147                 } catch (Exception e) {
148                         String msg = "File: " + file.getLocation().toOSString() + " Exception " + e.getMessage();
149                         status.addError(msg);
150                 }
151                 if (matches.size() > 0) {
152                         phpFiles.put(file, matches);
153                 }
154         }
155
156         private String readFileContent(final IFile file, final RefactoringStatus refStatus) {
157                 String result = null;
158                 try {
159                         InputStream is = file.getContents();
160                         byte[] buf = new byte[1024];
161                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
162                         int len = is.read(buf);
163                         while (len > 0) {
164                                 bos.write(buf, 0, len);
165                                 len = is.read(buf);
166                         }
167                         is.close();
168                         result = new String(bos.toByteArray());
169                 } catch (Exception ex) {
170                         String msg = ex.toString();
171                         refStatus.addFatalError(msg);
172                         String pluginId = PHPeclipsePlugin.getPluginId();
173                         IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
174                         PHPeclipsePlugin.getDefault().getLog().log(status);
175                 }
176                 return result;
177         }
178
179 }