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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.refactoring.rename;
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;
18 import org.eclipse.core.resources.IFile;
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;
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;
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;
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;
63 import org.eclipse.jdt.ui.JavaElementLabels;
64 import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;
66 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
68 public class RenameLocalVariableProcessor extends JavaRenameProcessor implements IReferenceUpdating {
70 public ILocalVariable fLocalVariable;
71 public ICompilationUnit fCu;
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;
81 private boolean fIsComposite;
82 private GroupCategorySet fCategorySet;
83 private TextChangeManager fChangeManager;
84 private RenameAnalyzeUtil.LocalAnalyzePackage fLocalAnalyzePackage;
86 public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameLocalVariableProcessor"; //$NON-NLS-1$
89 * Creates a new rename local variable processor.
90 * @param localVariable the local variable, or <code>null</code> if invoked by scripting
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$
101 public RenameLocalVariableProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
103 RefactoringStatus initializeStatus= initialize(arguments);
104 status.merge(initializeStatus);
108 * Creates a new rename local variable processor.
110 * This constructor is only used by <code>RenameTypeProcessor</code>.
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
118 RenameLocalVariableProcessor(ILocalVariable localVariable, TextChangeManager manager, CompilationUnit node, GroupCategorySet categorySet) {
120 fChangeManager= manager;
121 fCategorySet= categorySet;
122 fCompilationUnitNode= node;
127 * @see org.eclipse.jdt.internal.corext.refactoring.rename.JavaRenameProcessor#getAffectedProjectNatures()
130 protected final String[] getAffectedProjectNatures() throws CoreException {
131 return JavaProcessors.computeAffectedNatures(fLocalVariable);
135 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getElements()
138 public Object[] getElements() {
139 return new Object[] { fLocalVariable };
143 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getIdentifier()
146 public String getIdentifier() {
151 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
154 public String getProcessorName() {
155 return RefactoringCoreMessages.RenameTempRefactoring_rename;
159 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
162 public boolean isApplicable() throws CoreException {
163 return RefactoringAvailabilityTester.isRenameAvailable(fLocalVariable);
167 * @see org.eclipse.jdt.internal.corext.refactoring.rename.JavaRenameProcessor#getUpdateReferences()
169 public boolean getUpdateReferences() {
170 return fUpdateReferences;
174 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating#setUpdateReferences(boolean)
176 public void setUpdateReferences(boolean updateReferences) {
177 fUpdateReferences= updateReferences;
181 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getCurrentElementName()
183 public String getCurrentElementName() {
188 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getNewElementName()
191 public String getNewElementName() {
196 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#setNewElementName(java.lang.String)
199 public void setNewElementName(String newName) {
200 Assert.isNotNull(newName);
205 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#getNewElement()
207 public Object getNewElement() {
208 return null; //cannot create an ILocalVariable
212 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
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);
221 return new RefactoringStatus();
224 private void initAST() {
226 fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, null);
227 ISourceRange sourceRange= fLocalVariable.getNameRange();
228 ASTNode name= NodeFinder.perform(fCompilationUnitNode, sourceRange);
231 if (name.getParent() instanceof VariableDeclaration)
232 fTempDeclarationNode= (VariableDeclaration) name.getParent();
235 private void initNames(){
236 fCurrentName= fTempDeclarationNode.getName().getIdentifier();
240 protected RenameModifications computeRenameModifications() throws CoreException {
241 RenameModifications result= new RenameModifications();
242 return result.generated_4357821296503714223(this);
246 protected IFile[] getChangedFiles() throws CoreException {
247 return new IFile[] {ResourceUtil.getFile(fCu)};
251 public int getSaveMode() {
252 return RefactoringSaveHelper.SAVE_NOTHING;
256 protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context)
257 throws CoreException, OperationCanceledException {
259 pm.beginTask("", 1); //$NON-NLS-1$
261 RefactoringStatus result= checkNewElementName(fNewName);
262 if (result.hasFatalError())
266 LocalAnalyzePackage[] localAnalyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[] { fLocalAnalyzePackage };
267 result.merge(RenameAnalyzeUtil.analyzeLocalRenames(localAnalyzePackages, fChange, fCompilationUnitNode, true));
273 // end of life cycle for this processor
275 fCompilationUnitNode= null;
276 fTempDeclarationNode= null;
282 * @see org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating#checkNewElementName(java.lang.String)
284 public RefactoringStatus checkNewElementName(String newName) throws JavaModelException {
285 RefactoringStatus result= Checks.checkFieldName(newName, fCu);
286 if (! Checks.startsWithLowerCase(newName))
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 }));
292 result.addWarning(RefactoringCoreMessages.RenameTempRefactoring_lowercase);
297 private void createEdits() {
298 TextEdit declarationEdit= createRenameEdit(fTempDeclarationNode.getName().getStartPosition());
299 TextEdit[] allRenameEdits= getAllRenameEdits(declarationEdit);
301 TextEdit[] allUnparentedRenameEdits= new TextEdit[allRenameEdits.length];
302 TextEdit unparentedDeclarationEdit= null;
304 fChange= new CompilationUnitChange(RefactoringCoreMessages.RenameTempRefactoring_rename, fCu);
305 MultiTextEdit rootEdit= new MultiTextEdit();
306 fChange.setEdit(rootEdit);
307 fChange.setKeepPreviewEdits(true);
309 for (int i= 0; i < allRenameEdits.length; i++) {
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);
315 // Add a separate copy for problem reporting
316 allUnparentedRenameEdits[i]= allRenameEdits[i].copy();
317 if (allRenameEdits[i].equals(declarationEdit))
318 unparentedDeclarationEdit= allUnparentedRenameEdits[i];
320 rootEdit.addChild(allRenameEdits[i]);
321 fChange.addTextEditGroup(new TextEditGroup(RefactoringCoreMessages.RenameTempRefactoring_changeName, allRenameEdits[i]));
324 // store information for analysis
326 fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(unparentedDeclarationEdit, allUnparentedRenameEdits);
328 fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(declarationEdit, allRenameEdits);
331 private TextEdit[] getAllRenameEdits(TextEdit declarationEdit) {
332 if (! fUpdateReferences)
333 return new TextEdit[] { declarationEdit };
335 TempOccurrenceAnalyzer fTempAnalyzer= new TempOccurrenceAnalyzer(fTempDeclarationNode, true);
336 int[] referenceOffsets= fTempAnalyzer.generated_2804555612629923286();
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;
345 private TextEdit createRenameEdit(int offset) {
346 return new ReplaceEdit(offset, fCurrentName.length(), fNewName);
350 public Change createChange(IProgressMonitor monitor) throws CoreException {
352 monitor.beginTask(RefactoringCoreMessages.RenameTypeProcessor_creating_changes, 1);
354 RenameJavaElementDescriptor descriptor= createRefactoringDescriptor();
355 fChange.setDescriptor(new RefactoringChangeDescriptor(descriptor));
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);
381 private RefactoringStatus initialize(JavaRefactoringArguments extended) {
382 return extended.generated_1384567091643529(this);
385 public RenameAnalyzeUtil.LocalAnalyzePackage getLocalAnalyzePackage() {
386 return fLocalAnalyzePackage;
389 public RenameLocalVariableProcessor generated_2543151065218218596(RenameTypeProcessor renametypeprocessor) {
390 setUpdateReferences(renametypeprocessor.getUpdateReferences());