Added a new refactoring action: net.sourceforge.phpdt.ltk.ui.actions.RenameLocalVariable
[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 import java.util.Iterator;
10 import java.util.List;
11
12 import net.sourceforge.phpdt.core.ISourceRange;
13 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
14 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
15 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
16 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
17 import net.sourceforge.phpdt.internal.core.SourceMethod;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.ltk.core.refactoring.Change;
28 import org.eclipse.ltk.core.refactoring.CompositeChange;
29 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
30 import org.eclipse.ltk.core.refactoring.TextFileChange;
31 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
32 import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
33 import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
34 import org.eclipse.text.edits.MultiTextEdit;
35 import org.eclipse.text.edits.ReplaceEdit;
36
37 /**
38  * <p>
39  * delegate object that contains the logic used by the processor.
40  * </p>
41  *
42  */
43 public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
44
45         public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
46                 super(info);
47         }
48
49         RefactoringStatus checkInitialConditions() {
50                 RefactoringStatus result = new RefactoringStatus();
51                 IFile sourceFile = info.getSourceFile();
52                 if (sourceFile == null || !sourceFile.exists()) {
53                         result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
54                 } else if (info.getSourceFile().isReadOnly()) {
55                         result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
56                 } else if (isEmpty(info.getOldName())) {
57                         // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
58                         result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
59                 }
60                 return result;
61         }
62
63         RefactoringStatus checkFinalConditions(final IProgressMonitor pm, final CheckConditionsContext ctxt) {
64                 RefactoringStatus result = new RefactoringStatus();
65                 pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
66                 // do something long-running here: traverse the entire project (or even
67                 // workspace) to look for all *.p files with the same bundle
68                 // base name
69                 IFile file = info.getSourceFile();
70                 IProject project = file.getProject();
71                 try {
72                         SourceMethod method = info.getMethod();
73                         ISourceRange range = method.getSourceRange();
74                         if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
75                                 determineMethodOffsets(file, range.getOffset(), range.getLength(), result);
76                         }
77                 } catch (CoreException e) {
78                         String msg = "Project: " + project.getLocation().toOSString() + " CoreException " + e.getMessage();
79                         result.addError(msg);
80                 } catch (Exception e) {
81                         String msg = "Project: " + project.getLocation().toOSString() + " Exception " + e.getMessage();
82                         result.addError(msg);
83                 }
84
85                 pm.worked(50);
86
87                 if (ctxt != null) {
88                         IFile[] files = new IFile[phpFiles.size()];
89                         phpFiles.keySet().toArray(files);
90                         IConditionChecker checker = ctxt.getChecker(ValidateEditChecker.class);
91                         ValidateEditChecker editChecker = (ValidateEditChecker) checker;
92                         editChecker.addFiles(files);
93                 }
94                 pm.done();
95                 return result;
96         }
97
98         protected void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
99                 try {
100                         pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges, 100);
101                         // all files in the same bundle
102                         rootChange.addAll(createChangesForContainer(pm));
103                 } finally {
104                         pm.done();
105                 }
106         }
107
108         // finds the offsets of the identifier to rename
109         // usually, this would be the job of a proper parser;
110         // using a primitive brute-force approach here
111         private void determineMethodOffsets(final IFile file, int offset, int length, final RefactoringStatus status) {
112                 ArrayList matches = new ArrayList();
113                 try {
114                         String content = readFileContent(file, status);
115                         String methodString = content.substring(offset, offset + length);
116                         Scanner scanner = new Scanner(true, false);
117                         scanner.setSource(methodString.toCharArray());
118                         scanner.setPHPMode(true);
119                         char[] word = info.getOldName().toCharArray();
120
121                         int fToken = ITerminalSymbols.TokenNameEOF;
122                         try {
123                                 fToken = scanner.getNextToken();
124                                 while (fToken != ITerminalSymbols.TokenNameEOF) {
125                                         if (fToken == ITerminalSymbols.TokenNameVariable) {
126                                                 if (scanner.equalsCurrentTokenSource(word)) {
127                                                         matches.add(Integer.valueOf(scanner.getCurrentTokenStartPosition() + offset));
128                                                 }
129                                         }
130                                         fToken = scanner.getNextToken();
131                                 }
132
133                         } catch (InvalidInputException e) {
134                                 String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
135                                 status.addError(msg);
136                         } catch (SyntaxError e) {
137                                 String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
138                                 status.addError(msg);
139                         }
140
141                 } catch (Exception e) {
142                         String msg = "File: " + file.getLocation().toOSString() + " Exception " + e.getMessage();
143                         status.addError(msg);
144                 }
145                 if (matches.size() > 0) {
146                         phpFiles.put(file, matches);
147                 }
148         }
149
150         private String readFileContent(final IFile file, final RefactoringStatus refStatus) {
151                 String result = null;
152                 try {
153                         InputStream is = file.getContents();
154                         byte[] buf = new byte[1024];
155                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
156                         int len = is.read(buf);
157                         while (len > 0) {
158                                 bos.write(buf, 0, len);
159                                 len = is.read(buf);
160                         }
161                         is.close();
162                         result = new String(bos.toByteArray());
163                 } catch (Exception ex) {
164                         String msg = ex.toString();
165                         refStatus.addFatalError(msg);
166                         String pluginId = PHPeclipsePlugin.getPluginId();
167                         IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
168                         PHPeclipsePlugin.getDefault().getLog().log(status);
169                 }
170                 return result;
171         }
172
173 }