]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/rename/RenameLocalVariableProcessor.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / rename / RenameLocalVariableProcessor.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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 org.eclipse.core.runtime.Assert;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.core.runtime.OperationCanceledException;
17
18 import org.eclipse.core.resources.IFile;
19
20 import org.eclipse.text.edits.MultiTextEdit;
21 import org.eclipse.text.edits.ReplaceEdit;
22 import org.eclipse.text.edits.TextEdit;
23 import org.eclipse.text.edits.TextEditGroup;
24
25 import org.eclipse.ltk.core.refactoring.Change;
26 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
27 import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
28 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
29 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
30 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
31
32 import org.eclipse.jdt.core.ICompilationUnit;
33 import org.eclipse.jdt.core.IJavaElement;
34 import org.eclipse.jdt.core.IJavaProject;
35 import org.eclipse.jdt.core.ILocalVariable;
36 import org.eclipse.jdt.core.ISourceRange;
37 import org.eclipse.jdt.core.JavaModelException;
38 import org.eclipse.jdt.core.dom.ASTNode;
39 import org.eclipse.jdt.core.dom.CompilationUnit;
40 import org.eclipse.jdt.core.dom.Initializer;
41 import org.eclipse.jdt.core.dom.MethodDeclaration;
42 import org.eclipse.jdt.core.dom.NodeFinder;
43 import org.eclipse.jdt.core.dom.VariableDeclaration;
44 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
45 import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
46 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
47
48 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
49 import org.eclipse.jdt.internal.corext.refactoring.Checks;
50 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
51 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
52 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
53 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
54 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
55 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
56 import org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil.LocalAnalyzePackage;
57 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
58 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
59 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
60 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
61 import org.eclipse.jdt.internal.corext.util.Messages;
62
63 import org.eclipse.jdt.ui.JavaElementLabels;
64 import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;
65
66 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
67
68 public class RenameLocalVariableProcessor extends JavaRenameProcessor implements IReferenceUpdating {
69
70         public ILocalVariable fLocalVariable;
71         public ICompilationUnit fCu;
72
73         //the following fields are set or modified after the construction
74         public boolean fUpdateReferences;
75         private String fCurrentName;
76         private String fNewName;
77         private CompilationUnit fCompilationUnitNode;
78         private VariableDeclaration fTempDeclarationNode;
79         private CompilationUnitChange fChange;
80
81         private boolean fIsComposite;
82         private GroupCategorySet fCategorySet;
83         private TextChangeManager fChangeManager;
84         private RenameAnalyzeUtil.LocalAnalyzePackage fLocalAnalyzePackage;
85
86         public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameLocalVariableProcessor"; //$NON-NLS-1$
87
88         /**
89          * Creates a new rename local variable processor.
90          * @param localVariable the local variable, or <code>null</code> if invoked by scripting
91          */
92         public RenameLocalVariableProcessor(ILocalVariable localVariable) {
93                 fLocalVariable= localVariable;
94                 fUpdateReferences= true;
95                 if (localVariable != null)
96                         fCu= (ICompilationUnit) localVariable.getAncestor(IJavaElement.COMPILATION_UNIT);
97                 fNewName= ""; //$NON-NLS-1$
98                 fIsComposite= false;
99         }
100
101         public RenameLocalVariableProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
102                 this(null);
103                 RefactoringStatus initializeStatus= initialize(arguments);
104                 status.merge(initializeStatus);
105         }
106
107         /**
108          * Creates a new rename local variable processor.
109          * <p>
110          * This constructor is only used by <code>RenameTypeProcessor</code>.
111          * </p>
112          *
113          * @param localVariable the local variable
114          * @param manager the change manager
115          * @param node the compilation unit node
116          * @param categorySet the group category set
117          */
118         RenameLocalVariableProcessor(ILocalVariable localVariable, TextChangeManager manager, CompilationUnit node, GroupCategorySet categorySet) {
119                 this(localVariable);
120                 fChangeManager= manager;
121                 fCategorySet= categorySet;
122                 fCompilationUnitNode= node;
123                 fIsComposite= true;
124         }
125
126         /*
127          * @see org.eclipse.jdt.internal.corext.refactoring.rename.JavaRenameProcessor#getAffectedProjectNatures()
128          */
129         @Override
130         protected final String[] getAffectedProjectNatures() throws CoreException {
131                 return JavaProcessors.computeAffectedNatures(fLocalVariable);
132         }
133
134         /*
135          * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements()
136          */
137         @Override
138         public Object[] getElements() {
139                 return new Object[] { fLocalVariable };
140         }
141
142         /*
143          * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier()
144          */
145         @Override
146         public String getIdentifier() {
147                 return IDENTIFIER;
148         }
149
150         /*
151          * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
152          */
153         @Override
154         public String getProcessorName() {
155                 return RefactoringCoreMessages.RenameTempRefactoring_rename;
156         }
157
158         /*
159          * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
160          */
161         @Override
162         public boolean isApplicable() throws CoreException {
163                 return RefactoringAvailabilityTester.isRenameAvailable(fLocalVariable);
164         }
165
166         /*
167          * @see org.eclipse.jdt.internal.corext.refactoring.rename.JavaRenameProcessor#getUpdateReferences()
168          */
169         public boolean getUpdateReferences() {
170                 return fUpdateReferences;
171         }
172
173         /*
174          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating#setUpdateReferences(boolean)
175          */
176         public void setUpdateReferences(boolean updateReferences) {
177                 fUpdateReferences= updateReferences;
178         }
179
180         /*
181          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getCurrentElementName()
182          */
183         public String getCurrentElementName() {
184                 return fCurrentName;
185         }
186
187         /*
188          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getNewElementName()
189          */
190         @Override
191         public String getNewElementName() {
192                 return fNewName;
193         }
194
195         /*
196          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#setNewElementName(java.lang.String)
197          */
198         @Override
199         public void setNewElementName(String newName) {
200                 Assert.isNotNull(newName);
201                 fNewName= newName;
202         }
203
204         /*
205          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getNewElement()
206          */
207         public Object getNewElement() {
208                 return null; //cannot create an ILocalVariable
209         }
210
211         @Override
212         public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
213                 initAST();
214                 if (fTempDeclarationNode == null || fTempDeclarationNode.resolveBinding() == null)
215                         return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameTempRefactoring_must_select_local);
216                 if (! Checks.isDeclaredIn(fTempDeclarationNode, MethodDeclaration.class)
217                  && ! Checks.isDeclaredIn(fTempDeclarationNode, Initializer.class))
218                         return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameTempRefactoring_only_in_methods_and_initializers);
219
220                 initNames();
221                 return new RefactoringStatus();
222         }
223
224         private void initAST() {
225                 if (!fIsComposite)
226                         fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, null);
227                 ISourceRange sourceRange= fLocalVariable.getNameRange();
228                 ASTNode name= NodeFinder.perform(fCompilationUnitNode, sourceRange);
229                 if (name == null)
230                         return;
231                 if (name.getParent() instanceof VariableDeclaration)
232                         fTempDeclarationNode= (VariableDeclaration) name.getParent();
233         }
234
235         private void initNames(){
236                 fCurrentName= fTempDeclarationNode.getName().getIdentifier();
237         }
238
239         @Override
240         protected RenameModifications computeRenameModifications() throws CoreException {
241                 RenameModifications result= new RenameModifications();
242                 return result.generated_4357821296503714223(this);
243         }
244
245         @Override
246         protected IFile[] getChangedFiles() throws CoreException {
247                 return new IFile[] {ResourceUtil.getFile(fCu)};
248         }
249
250         @Override
251         public int getSaveMode() {
252                 return RefactoringSaveHelper.SAVE_NOTHING;
253         }
254
255         @Override
256         protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context)
257                         throws CoreException, OperationCanceledException {
258                 try {
259                         pm.beginTask("", 1);     //$NON-NLS-1$
260
261                         RefactoringStatus result= checkNewElementName(fNewName);
262                         if (result.hasFatalError())
263                                 return result;
264                         createEdits();
265                         if (!fIsComposite) {
266                                 LocalAnalyzePackage[] localAnalyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[] { fLocalAnalyzePackage };
267                                 result.merge(RenameAnalyzeUtil.analyzeLocalRenames(localAnalyzePackages, fChange, fCompilationUnitNode, true));
268                         }
269                         return result;
270                 } finally {
271                         pm.done();
272                         if (fIsComposite) {
273                                 // end of life cycle for this processor
274                                 fChange= null;
275                                 fCompilationUnitNode= null;
276                                 fTempDeclarationNode= null;
277                         }
278                 }
279         }
280
281         /*
282          * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#checkNewElementName(java.lang.String)
283          */
284         public RefactoringStatus checkNewElementName(String newName) throws JavaModelException {
285                 RefactoringStatus result= Checks.checkFieldName(newName, fCu);
286                 if (! Checks.startsWithLowerCase(newName))
287                         if (fIsComposite) {
288                                 final String nameOfParent= JavaElementLabels.getElementLabel(fLocalVariable.getParent(), JavaElementLabels.ALL_DEFAULT);
289                                 final String nameOfType= JavaElementLabels.getElementLabel(fLocalVariable.getAncestor(IJavaElement.TYPE), JavaElementLabels.ALL_DEFAULT);
290                                 result.addWarning(Messages.format(RefactoringCoreMessages.RenameTempRefactoring_lowercase2, new String[] { BasicElementLabels.getJavaElementName(newName), nameOfParent, nameOfType }));
291                         } else {
292                                 result.addWarning(RefactoringCoreMessages.RenameTempRefactoring_lowercase);
293                         }
294                 return result;
295         }
296
297         private void createEdits() {
298                 TextEdit declarationEdit= createRenameEdit(fTempDeclarationNode.getName().getStartPosition());
299                 TextEdit[] allRenameEdits= getAllRenameEdits(declarationEdit);
300
301                 TextEdit[] allUnparentedRenameEdits= new TextEdit[allRenameEdits.length];
302                 TextEdit unparentedDeclarationEdit= null;
303
304                 fChange= new CompilationUnitChange(RefactoringCoreMessages.RenameTempRefactoring_rename, fCu);
305                 MultiTextEdit rootEdit= new MultiTextEdit();
306                 fChange.setEdit(rootEdit);
307                 fChange.setKeepPreviewEdits(true);
308
309                 for (int i= 0; i < allRenameEdits.length; i++) {
310                         if (fIsComposite) {
311                                 // Add a copy of the text edit (text edit may only have one
312                                 // parent) to keep problem reporting code clean
313                                 TextChangeCompatibility.addTextEdit(fChangeManager.get(fCu), RefactoringCoreMessages.RenameTempRefactoring_changeName, allRenameEdits[i].copy(), fCategorySet);
314
315                                 // Add a separate copy for problem reporting
316                                 allUnparentedRenameEdits[i]= allRenameEdits[i].copy();
317                                 if (allRenameEdits[i].equals(declarationEdit))
318                                         unparentedDeclarationEdit= allUnparentedRenameEdits[i];
319                         }
320                         rootEdit.addChild(allRenameEdits[i]);
321                         fChange.addTextEditGroup(new TextEditGroup(RefactoringCoreMessages.RenameTempRefactoring_changeName, allRenameEdits[i]));
322                 }
323
324                 // store information for analysis
325                 if (fIsComposite) {
326                         fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(unparentedDeclarationEdit, allUnparentedRenameEdits);
327                 } else
328                         fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(declarationEdit, allRenameEdits);
329         }
330
331         private TextEdit[] getAllRenameEdits(TextEdit declarationEdit) {
332                 if (! fUpdateReferences)
333                         return new TextEdit[] { declarationEdit };
334
335                 TempOccurrenceAnalyzer fTempAnalyzer= new TempOccurrenceAnalyzer(fTempDeclarationNode, true);
336                 int[] referenceOffsets= fTempAnalyzer.generated_2804555612629923286();
337
338                 TextEdit[] allRenameEdits= new TextEdit[referenceOffsets.length + 1];
339                 for (int i= 0; i < referenceOffsets.length; i++)
340                         allRenameEdits[i]= createRenameEdit(referenceOffsets[i]);
341                 allRenameEdits[referenceOffsets.length]= declarationEdit;
342                 return allRenameEdits;
343         }
344
345         private TextEdit createRenameEdit(int offset) {
346                 return new ReplaceEdit(offset, fCurrentName.length(), fNewName);
347         }
348
349         @Override
350         public Change createChange(IProgressMonitor monitor) throws CoreException {
351                 try {
352                         monitor.beginTask(RefactoringCoreMessages.RenameTypeProcessor_creating_changes, 1);
353
354                         RenameJavaElementDescriptor descriptor= createRefactoringDescriptor();
355                         fChange.setDescriptor(new RefactoringChangeDescriptor(descriptor));
356                         return fChange;
357                 } finally {
358                         monitor.done();
359                 }
360         }
361
362         private RenameJavaElementDescriptor createRefactoringDescriptor() {
363                 String project= null;
364                 IJavaProject javaProject= fCu.getJavaProject();
365                 if (javaProject != null)
366                         project= javaProject.getElementName();
367                 final String header= Messages.format(RefactoringCoreMessages.RenameLocalVariableProcessor_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fCurrentName), JavaElementLabels.getElementLabel(fLocalVariable.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED), BasicElementLabels.getJavaElementName(fNewName)});
368                 final String description= Messages.format(RefactoringCoreMessages.RenameLocalVariableProcessor_descriptor_description_short, BasicElementLabels.getJavaElementName(fCurrentName));
369                 final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString();
370                 final RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_LOCAL_VARIABLE);
371                 descriptor.setProject(project);
372                 descriptor.setDescription(description);
373                 descriptor.setComment(comment);
374                 descriptor.setFlags(RefactoringDescriptor.NONE);
375                 descriptor.setJavaElement(fLocalVariable);
376                 descriptor.setNewName(getNewElementName());
377                 descriptor.setUpdateReferences(fUpdateReferences);
378                 return descriptor;
379         }
380
381         private RefactoringStatus initialize(JavaRefactoringArguments extended) {
382                 return extended.generated_1384567091643529(this);
383         }
384
385         public RenameAnalyzeUtil.LocalAnalyzePackage getLocalAnalyzePackage() {
386                 return fLocalAnalyzePackage;
387         }
388
389         public RenameLocalVariableProcessor generated_2543151065218218596(RenameTypeProcessor renametypeprocessor) {
390                 setUpdateReferences(renametypeprocessor.getUpdateReferences());
391                 return this;
392         }
393 }