KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > rename > RenameTempRefactoring


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.rename;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashSet JavaDoc;
17
18 import org.eclipse.text.edits.MultiTextEdit;
19 import org.eclipse.text.edits.ReplaceEdit;
20 import org.eclipse.text.edits.TextEdit;
21 import org.eclipse.text.edits.TextEditGroup;
22
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.NullProgressMonitor;
26
27 import org.eclipse.jdt.core.ICompilationUnit;
28 import org.eclipse.jdt.core.IJavaElement;
29 import org.eclipse.jdt.core.JavaModelException;
30 import org.eclipse.jdt.core.compiler.IProblem;
31 import org.eclipse.jdt.core.dom.AST;
32 import org.eclipse.jdt.core.dom.ASTNode;
33 import org.eclipse.jdt.core.dom.ASTParser;
34 import org.eclipse.jdt.core.dom.ASTVisitor;
35 import org.eclipse.jdt.core.dom.CompilationUnit;
36 import org.eclipse.jdt.core.dom.IBinding;
37 import org.eclipse.jdt.core.dom.IVariableBinding;
38 import org.eclipse.jdt.core.dom.Initializer;
39 import org.eclipse.jdt.core.dom.MethodDeclaration;
40 import org.eclipse.jdt.core.dom.Name;
41 import org.eclipse.jdt.core.dom.SimpleName;
42 import org.eclipse.jdt.core.dom.VariableDeclaration;
43
44 import org.eclipse.jface.text.Region;
45
46 import org.eclipse.jdt.internal.corext.Assert;
47 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
48 import org.eclipse.jdt.internal.corext.refactoring.Checks;
49 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
50 import org.eclipse.jdt.internal.corext.refactoring.base.JavaRefactorings;
51 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
52 import org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating;
53 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
54 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
55 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
56
57 import org.eclipse.ltk.core.refactoring.Change;
58 import org.eclipse.ltk.core.refactoring.Refactoring;
59 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
60 import org.eclipse.ltk.core.refactoring.TextChange;
61
62 public class RenameTempRefactoring extends Refactoring implements INameUpdating, IReferenceUpdating {
63     private static class ProblemNodeFinder {
64     
65         private ProblemNodeFinder() {
66             //static
67
}
68         
69         public static SimpleName[] getProblemNodes(ASTNode methodNode, TextEdit[] edits, TextChange change, String JavaDoc key) {
70             NameNodeVisitor visitor= new NameNodeVisitor(edits, change, key);
71             methodNode.accept(visitor);
72             return visitor.getProblemNodes();
73         }
74         
75         private static class NameNodeVisitor extends ASTVisitor {
76     
77             private Collection JavaDoc fRanges;
78             private Collection JavaDoc fProblemNodes;
79             private String JavaDoc fKey;
80     
81             public NameNodeVisitor(TextEdit[] edits, TextChange change, String JavaDoc key) {
82                 Assert.isNotNull(edits);
83                 Assert.isNotNull(key);
84                 fRanges= new HashSet JavaDoc(Arrays.asList(RefactoringAnalyzeUtil.getNewRanges(edits, change)));
85                 fProblemNodes= new ArrayList JavaDoc(0);
86                 fKey= key;
87             }
88     
89             public SimpleName[] getProblemNodes() {
90                 return (SimpleName[]) fProblemNodes.toArray(new SimpleName[fProblemNodes.size()]);
91             }
92     
93             private static VariableDeclaration getVariableDeclaration(Name node) {
94                 IBinding binding= node.resolveBinding();
95                 if (binding == null && node.getParent() instanceof VariableDeclaration)
96                     return (VariableDeclaration) node.getParent();
97     
98                 if (binding != null && binding.getKind() == IBinding.VARIABLE) {
99                     CompilationUnit cu= (CompilationUnit) ASTNodes.getParent(node, CompilationUnit.class);
100                     return ASTNodes.findVariableDeclaration(((IVariableBinding) binding), cu);
101                 }
102                 return null;
103             }
104     
105             //----- visit methods
106

107             public boolean visit(SimpleName node) {
108                 VariableDeclaration decl= getVariableDeclaration(node);
109                 if (decl == null)
110                     return super.visit(node);
111                 boolean keysEqual= fKey.equals(RefactoringAnalyzeUtil.getFullBindingKey(decl));
112                 boolean rangeInSet= fRanges.contains(new Region(node.getStartPosition(), node.getLength()));
113     
114                 if (keysEqual && !rangeInSet)
115                     fProblemNodes.add(node);
116     
117                 if (!keysEqual && rangeInSet)
118                     fProblemNodes.add(node);
119     
120                 return super.visit(node);
121             }
122         }
123     }
124     
125     private final int fSelectionStart;
126     private final int fSelectionLength;
127     private final ICompilationUnit fCu;
128     
129     //the following fields are set or modified after the construction
130
private boolean fUpdateReferences;
131     private String JavaDoc fCurrentName;
132     private String JavaDoc fNewName;
133     private CompilationUnit fCompilationUnitNode;
134     private VariableDeclaration fTempDeclarationNode;
135     private TextChange fChange;
136     
137     private RenameTempRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength) {
138         Assert.isTrue(selectionStart >= 0);
139         Assert.isTrue(selectionLength >= 0);
140         Assert.isTrue(cu.exists());
141         fUpdateReferences= true;
142         fSelectionStart= selectionStart;
143         fSelectionLength= selectionLength;
144         fCu= cu;
145         fNewName= "";//the only thing we can set //$NON-NLS-1$
146
}
147
148     public static boolean isAvailable(IJavaElement element) {
149         return element != null && element.getElementType() == IJavaElement.LOCAL_VARIABLE;
150     }
151
152     public static RenameTempRefactoring create(ICompilationUnit cu, int selectionStart, int selectionLength) {
153         return new RenameTempRefactoring(cu, selectionStart, selectionLength);
154     }
155     
156     public Object JavaDoc getNewElement(){
157         return null; //?????
158
}
159     
160     /* non java-doc
161      * @see IRefactoring#getName()
162      */

163     public String JavaDoc getName() {
164         return RefactoringCoreMessages.getString("RenameTempRefactoring.rename"); //$NON-NLS-1$
165
}
166
167     /*
168      * @see IReferenceUpdatingRefactoring#canEnableUpdateReferences()
169      */

170     public boolean canEnableUpdateReferences() {
171         return true;
172     }
173
174     /*
175      * @see IReferenceUpdatingRefactoring#getUpdateReferences()
176      */

177     public boolean getUpdateReferences() {
178         return fUpdateReferences;
179     }
180
181     /*
182      * @see IReferenceUpdatingRefactoring#setUpdateReferences()
183      */

184     public void setUpdateReferences(boolean updateReferences) {
185         fUpdateReferences= updateReferences;
186     }
187     
188     /*
189      * @see IRenameRefactoring#setNewName
190      */

191     public void setNewElementName(String JavaDoc newName) {
192         Assert.isNotNull(newName);
193         fNewName= newName;
194     }
195
196     /*
197      * @see IRenameRefactoring#getNewName()
198      */

199     public String JavaDoc getNewElementName() {
200         return fNewName;
201     }
202
203     /*
204      * @see IRenameRefactoring#getCurrentName()
205      */

206     public String JavaDoc getCurrentElementName() {
207         return fCurrentName;
208     }
209
210         //--- preconditions
211

212     /* non java-doc
213      * @see Refactoring#checkActivation(IProgressMonitor)
214      */

215     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
216         initAST();
217         if (fTempDeclarationNode == null || fTempDeclarationNode.resolveBinding() == null)
218             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("RenameTempRefactoring.must_select_local")); //$NON-NLS-1$
219
if (! Checks.isDeclaredIn(fTempDeclarationNode, MethodDeclaration.class)
220          && ! Checks.isDeclaredIn(fTempDeclarationNode, Initializer.class))
221             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("RenameTempRefactoring.only_in_methods_and_initializers")); //$NON-NLS-1$
222

223         initNames();
224         return new RefactoringStatus();
225     }
226
227     private void initAST(){
228         fCompilationUnitNode= new RefactoringASTParser(AST.JLS2).parse(fCu, true);
229         fTempDeclarationNode= TempDeclarationFinder.findTempDeclaration(fCompilationUnitNode, fSelectionStart, fSelectionLength);
230     }
231     
232     private void initNames(){
233         fCurrentName= fTempDeclarationNode.getName().getIdentifier();
234     }
235     
236     /*
237      * @see IRenameRefactoring#checkNewName()
238      */

239     public RefactoringStatus checkNewElementName(String JavaDoc newName) throws JavaModelException {
240         RefactoringStatus result= Checks.checkFieldName(newName);
241         if (! Checks.startsWithLowerCase(newName))
242             result.addWarning(RefactoringCoreMessages.getString("RenameTempRefactoring.lowercase")); //$NON-NLS-1$
243
return result;
244     }
245         
246     /* non java-doc
247      * @see Refactoring#checkInput(IProgressMonitor)
248      */

249     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
250         try {
251             pm.beginTask("", 1); //$NON-NLS-1$
252
RefactoringStatus result= new RefactoringStatus();
253             result.merge(Checks.validateModifiesFiles(
254                 ResourceUtil.getFiles(new ICompilationUnit[]{fCu}),
255                 getValidationContext()));
256             if (result.hasFatalError())
257                 return result;
258             
259             result.merge(checkNewElementName(fNewName));
260             if (result.hasFatalError())
261                 return result;
262             result.merge(analyzeAST());
263             return result;
264         } finally {
265             pm.done();
266         }
267     }
268         
269     private RefactoringStatus analyzeAST() throws CoreException{
270         TextEdit declarationEdit= createRenameEdit(fTempDeclarationNode.getName().getStartPosition());
271         TextEdit[] allRenameEdits= getAllRenameEdits(declarationEdit);
272         fChange= new CompilationUnitChange(RefactoringCoreMessages.getString("RenameTempRefactoring.rename"), fCu); //$NON-NLS-1$
273
MultiTextEdit rootEdit= new MultiTextEdit();
274         fChange.setEdit(rootEdit);
275         fChange.setKeepPreviewEdits(true);
276
277         String JavaDoc changeName= RefactoringCoreMessages.getFormattedString("RenameTempRefactoring.changeName", new String JavaDoc[]{fCurrentName, fNewName}); //$NON-NLS-1$
278
for (int i= 0; i < allRenameEdits.length; i++) {
279             rootEdit.addChild(allRenameEdits[i]);
280             fChange.addTextEditGroup(new TextEditGroup(changeName, allRenameEdits[i]));
281         }
282         String JavaDoc newCuSource= fChange.getPreviewContent(new NullProgressMonitor());
283         ASTParser p= ASTParser.newParser(AST.JLS2);
284         p.setSource(newCuSource.toCharArray());
285         p.setUnitName(fCu.getElementName());
286         p.setProject(fCu.getJavaProject());
287         p.setCompilerOptions(RefactoringASTParser.getCompilerOptions(fCu));
288         CompilationUnit newCUNode= (CompilationUnit) p.createAST(null);
289
290         RefactoringStatus result= new RefactoringStatus();
291         result.merge(analyzeCompileErrors(newCuSource, newCUNode));
292         if (result.hasError())
293             return result;
294         
295         String JavaDoc fullKey= RefactoringAnalyzeUtil.getFullBindingKey(fTempDeclarationNode);
296         ASTNode enclosing= getEnclosingBlockOrMethod(declarationEdit, fChange, newCUNode);
297         SimpleName[] problemNodes= ProblemNodeFinder.getProblemNodes(enclosing, allRenameEdits, fChange, fullKey);
298         result.merge(RefactoringAnalyzeUtil.reportProblemNodes(newCuSource, problemNodes));
299         return result;
300     }
301
302     private TextEdit[] getAllRenameEdits(TextEdit declarationEdit) {
303         if (! fUpdateReferences)
304             return new TextEdit[] { declarationEdit };
305         
306         TempOccurrenceAnalyzer fTempAnalyzer= new TempOccurrenceAnalyzer(fTempDeclarationNode, true);
307         fTempAnalyzer.perform();
308         int[] referenceOffsets= fTempAnalyzer.getReferenceAndJavadocOffsets();
309
310         TextEdit[] allRenameEdits= new TextEdit[referenceOffsets.length + 1];
311         for (int i= 0; i < referenceOffsets.length; i++)
312             allRenameEdits[i]= createRenameEdit(referenceOffsets[i]);
313         allRenameEdits[referenceOffsets.length]= declarationEdit;
314         return allRenameEdits;
315     }
316
317     private TextEdit createRenameEdit(int offset) {
318         return new ReplaceEdit(offset, fCurrentName.length(), fNewName);
319     }
320     
321     private ASTNode getEnclosingBlockOrMethod(TextEdit declarationEdit, TextChange change, CompilationUnit newCUNode) {
322         ASTNode enclosing= RefactoringAnalyzeUtil.getBlock(declarationEdit, change, newCUNode);
323         if (enclosing == null)
324             enclosing= RefactoringAnalyzeUtil.getMethodDeclaration(declarationEdit, change, newCUNode);
325         return enclosing;
326     }
327     
328     private RefactoringStatus analyzeCompileErrors(String JavaDoc newCuSource, CompilationUnit newCUNode) {
329         RefactoringStatus result= new RefactoringStatus();
330         IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fCompilationUnitNode);
331         for (int i= 0; i < newProblems.length; i++) {
332             IProblem problem= newProblems[i];
333             if (problem.isError())
334                 result.addEntry(JavaRefactorings.createStatusEntry(problem, newCuSource));
335         }
336         return result;
337     }
338     
339     //--- changes
340

341     /* non java-doc
342      * @see IRefactoring#createChange(IProgressMonitor)
343      */

344     public Change createChange(IProgressMonitor pm) throws CoreException {
345         pm.done();
346         return fChange;
347     }
348 }
349
Popular Tags