KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 import org.eclipse.core.runtime.SubProgressMonitor;
18
19 import org.eclipse.core.resources.IFile;
20
21 import org.eclipse.ltk.core.refactoring.Change;
22 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
23 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
24 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
25 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
26 import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
27
28 import org.eclipse.jdt.core.ICompilationUnit;
29 import org.eclipse.jdt.core.IJavaElement;
30 import org.eclipse.jdt.core.IJavaProject;
31 import org.eclipse.jdt.core.IMember;
32 import org.eclipse.jdt.core.IMethod;
33 import org.eclipse.jdt.core.ISourceRange;
34 import org.eclipse.jdt.core.IType;
35 import org.eclipse.jdt.core.ITypeParameter;
36 import org.eclipse.jdt.core.dom.ASTNode;
37 import org.eclipse.jdt.core.dom.ASTVisitor;
38 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
39 import org.eclipse.jdt.core.dom.CompilationUnit;
40 import org.eclipse.jdt.core.dom.EnumDeclaration;
41 import org.eclipse.jdt.core.dom.IBinding;
42 import org.eclipse.jdt.core.dom.ITypeBinding;
43 import org.eclipse.jdt.core.dom.SimpleName;
44 import org.eclipse.jdt.core.dom.TypeDeclaration;
45 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
46 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
47
48 import org.eclipse.jdt.internal.corext.SourceRange;
49 import org.eclipse.jdt.internal.corext.dom.Bindings;
50 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
51 import org.eclipse.jdt.internal.corext.refactoring.Checks;
52 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
53 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
54 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
55 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
56 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
57 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
58 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
59 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
60 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
61 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
62 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
63 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
64 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
65 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
66 import org.eclipse.jdt.internal.corext.util.Messages;
67
68 import org.eclipse.jdt.ui.JavaElementLabels;
69
70 import org.eclipse.jdt.internal.ui.JavaPlugin;
71 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper;
72
73 /**
74  * Rename processor to rename type parameters.
75  */

76 public final class RenameTypeParameterProcessor extends JavaRenameProcessor implements IReferenceUpdating {
77
78     /**
79      * AST visitor which searches for occurrences of the type parameter.
80      */

81     public final class RenameTypeParameterVisitor extends ASTVisitor {
82
83         /** The binding of the type parameter */
84         private final IBinding fBinding;
85
86         /** The node of the type parameter name */
87         private final SimpleName fName;
88
89         /** The compilation unit rewrite to use */
90         private final CompilationUnitRewrite fRewrite;
91
92         /** The status of the visiting process */
93         private final RefactoringStatus fStatus;
94
95         /**
96          * Creates a new rename type parameter visitor.
97          *
98          * @param rewrite
99          * the compilation unit rewrite to use
100          * @param range
101          * the source range of the type parameter
102          * @param status
103          * the status to update
104          */

105         public RenameTypeParameterVisitor(final CompilationUnitRewrite rewrite, final ISourceRange range, final RefactoringStatus status) {
106             super(true);
107             Assert.isNotNull(rewrite);
108             Assert.isNotNull(range);
109             Assert.isNotNull(status);
110             fRewrite= rewrite;
111             fName= (SimpleName) NodeFinder.perform(rewrite.getRoot(), range);
112             fBinding= fName.resolveBinding();
113             fStatus= status;
114         }
115
116         /**
117          * Returns the resulting change.
118          *
119          * @return the resulting change
120          * @throws CoreException
121          * if the change could not be created
122          */

123         public final Change getResult() throws CoreException {
124             return fRewrite.createChange();
125         }
126
127         public final boolean visit(final AnnotationTypeDeclaration node) {
128             final String JavaDoc name= node.getName().getIdentifier();
129             if (name.equals(getNewElementName())) {
130                 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String JavaDoc[] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node)));
131                 return false;
132             }
133             return true;
134         }
135
136         public final boolean visit(final EnumDeclaration node) {
137             final String JavaDoc name= node.getName().getIdentifier();
138             if (name.equals(getNewElementName())) {
139                 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String JavaDoc[] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node)));
140                 return false;
141             }
142             return true;
143         }
144
145         public final boolean visit(final SimpleName node) {
146             final ITypeBinding binding= node.resolveTypeBinding();
147             if (binding != null && binding.isTypeVariable() && Bindings.equals(binding, fBinding) && node.getIdentifier().equals(fName.getIdentifier())) {
148                 if (node != fName) {
149                     if (fUpdateReferences)
150                         fRewrite.getASTRewrite().set(node, SimpleName.IDENTIFIER_PROPERTY, getNewElementName(), fRewrite.createGroupDescription(RefactoringCoreMessages.RenameTypeParameterRefactoring_update_type_parameter_reference));
151                 } else
152                     fRewrite.getASTRewrite().set(node, SimpleName.IDENTIFIER_PROPERTY, getNewElementName(), fRewrite.createGroupDescription(RefactoringCoreMessages.RenameTypeParameterRefactoring_update_type_parameter_declaration));
153             }
154             return true;
155         }
156
157         public final boolean visit(final TypeDeclaration node) {
158             final String JavaDoc name= node.getName().getIdentifier();
159             if (name.equals(getNewElementName())) {
160                 fStatus.addError(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_type_parameter_inner_class_clash, new String JavaDoc[] { name}), JavaStatusContext.create(fTypeParameter.getDeclaringMember().getCompilationUnit(), new SourceRange(node)));
161                 return false;
162             }
163             return true;
164         }
165     }
166
167     private static final String JavaDoc ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
168

169     /** The identifier of this processor */
170     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.renameTypeParameterProcessor"; //$NON-NLS-1$
171

172     /** The change object */
173     private Change fChange= null;
174
175     /** The type parameter to rename */
176     private ITypeParameter fTypeParameter;
177
178     /** Should references to the type parameter be updated? */
179     private boolean fUpdateReferences= true;
180
181     /**
182      * Creates a new rename type parameter processor.
183      *
184      * @param parameter
185      * the type parameter to rename, or <code>null</code> if invoked by scripting
186      */

187     public RenameTypeParameterProcessor(final ITypeParameter parameter) {
188         fTypeParameter= parameter;
189         if (parameter != null)
190             setNewElementName(parameter.getElementName());
191     }
192
193     public final boolean canEnableUpdateReferences() {
194         return true;
195     }
196     
197     protected RenameModifications computeRenameModifications() throws CoreException {
198         RenameModifications result= new RenameModifications();
199         result.rename(fTypeParameter, new RenameArguments(getNewElementName(), getUpdateReferences()));
200         return result;
201     }
202
203     protected IFile[] getChangedFiles() throws CoreException {
204         return new IFile[] {ResourceUtil.getFile(fTypeParameter.getDeclaringMember().getCompilationUnit())};
205     }
206     
207     public int getSaveMode() {
208         return RefactoringSaveHelper.SAVE_NOTHING;
209     }
210     
211     protected final RefactoringStatus doCheckFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
212         Assert.isNotNull(monitor);
213         Assert.isNotNull(context);
214         final RefactoringStatus status= new RefactoringStatus();
215         try {
216             monitor.beginTask("", 5); //$NON-NLS-1$
217
monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_checking);
218             status.merge(Checks.checkIfCuBroken(fTypeParameter.getDeclaringMember()));
219             monitor.worked(1);
220             if (!status.hasFatalError()) {
221                 status.merge(checkNewElementName(getNewElementName()));
222                 monitor.worked(1);
223                 monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_searching);
224                 status.merge(createRenameChanges(new SubProgressMonitor(monitor, 2)));
225                 monitor.setTaskName(RefactoringCoreMessages.RenameTypeParameterRefactoring_checking);
226                 if (status.hasFatalError())
227                     return status;
228                 monitor.worked(1);
229             }
230         } finally {
231             monitor.done();
232         }
233         return status;
234     }
235
236     public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
237         Assert.isNotNull(monitor);
238         if (!fTypeParameter.exists())
239             return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.RenameTypeParameterRefactoring_deleted, fTypeParameter.getDeclaringMember().getCompilationUnit().getElementName()));
240         return Checks.checkIfCuBroken(fTypeParameter.getDeclaringMember());
241     }
242
243     public final RefactoringStatus checkNewElementName(final String JavaDoc name) throws CoreException {
244         Assert.isNotNull(name);
245         final RefactoringStatus result= Checks.checkTypeParameterName(name);
246         if (Checks.startsWithLowerCase(name))
247             result.addWarning(RefactoringCoreMessages.RenameTypeParameterRefactoring_should_start_lowercase);
248         if (Checks.isAlreadyNamed(fTypeParameter, name))
249             result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_another_name);
250
251         final IMember member= fTypeParameter.getDeclaringMember();
252         if (member instanceof IType) {
253             final IType type= (IType) member;
254             if (type.getTypeParameter(name).exists())
255                 result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_class_type_parameter_already_defined);
256         } else if (member instanceof IMethod) {
257             final IMethod method= (IMethod) member;
258             if (method.getTypeParameter(name).exists())
259                 result.addFatalError(RefactoringCoreMessages.RenameTypeParameterRefactoring_method_type_parameter_already_defined);
260         } else {
261             JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); //$NON-NLS-1$
262
Assert.isTrue(false);
263         }
264         return result;
265     }
266
267     public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
268         Assert.isNotNull(monitor);
269         try {
270             Change change= fChange;
271             if (change != null) {
272                 String JavaDoc project= null;
273                 IJavaProject javaProject= fTypeParameter.getJavaProject();
274                 if (javaProject != null)
275                     project= javaProject.getElementName();
276                 final String JavaDoc description= Messages.format(RefactoringCoreMessages.RenameTypeParameterProcessor_descriptor_description_short, fTypeParameter.getElementName());
277                 final String JavaDoc header= Messages.format(RefactoringCoreMessages.RenameTypeParameterProcessor_descriptor_description, new String JavaDoc[] { fTypeParameter.getElementName(), JavaElementLabels.getElementLabel(fTypeParameter.getDeclaringMember(), JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()});
278                 final String JavaDoc comment= new JDTRefactoringDescriptorComment(project, this, header).asString();
279                 final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE_PARAMETER);
280                 descriptor.setProject(project);
281                 descriptor.setDescription(description);
282                 descriptor.setComment(comment);
283                 descriptor.setFlags(RefactoringDescriptor.NONE);
284                 descriptor.setJavaElement(fTypeParameter);
285                 descriptor.setNewName(getNewElementName());
286                 descriptor.setUpdateReferences(fUpdateReferences);
287                 change= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameTypeParameterProcessor_change_name, new Change[] { change});
288             }
289             return change;
290         } finally {
291             fChange= null;
292             monitor.done();
293         }
294     }
295
296     /**
297      * Creates the necessary changes for the renaming of the type parameter.
298      *
299      * @param monitor
300      * the progress monitor to display progress
301      * @return the status of the operation
302      * @throws CoreException
303      * if the change could not be generated
304      */

305     private RefactoringStatus createRenameChanges(final IProgressMonitor monitor) throws CoreException {
306         Assert.isNotNull(monitor);
307         final RefactoringStatus status= new RefactoringStatus();
308         try {
309             monitor.beginTask(RefactoringCoreMessages.RenameTypeParameterRefactoring_searching, 2);
310             final ICompilationUnit cu= fTypeParameter.getDeclaringMember().getCompilationUnit();
311             final CompilationUnit root= RefactoringASTParser.parseWithASTProvider(cu, true, null);
312             final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu, root);
313             final IMember member= fTypeParameter.getDeclaringMember();
314             ASTNode declaration= null;
315             if (member instanceof IMethod) {
316                 declaration= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, root);
317             } else if (member instanceof IType) {
318                 declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, root);
319             } else {
320                 JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); //$NON-NLS-1$
321
Assert.isTrue(false);
322             }
323             monitor.worked(1);
324             final RenameTypeParameterVisitor visitor= new RenameTypeParameterVisitor(rewrite, fTypeParameter.getNameRange(), status);
325             if (declaration != null)
326                 declaration.accept(visitor);
327             fChange= visitor.getResult();
328         } finally {
329             monitor.done();
330         }
331         return status;
332     }
333
334     protected final String JavaDoc[] getAffectedProjectNatures() throws CoreException {
335         return JavaProcessors.computeAffectedNatures(fTypeParameter);
336     }
337
338     public final String JavaDoc getCurrentElementName() {
339         return fTypeParameter.getElementName();
340     }
341
342     public final Object JavaDoc[] getElements() {
343         return new Object JavaDoc[] { fTypeParameter};
344     }
345
346     public final String JavaDoc getIdentifier() {
347         return IDENTIFIER;
348     }
349     
350     public final Object JavaDoc getNewElement() throws CoreException {
351         final IMember member= fTypeParameter.getDeclaringMember();
352         if (member instanceof IType) {
353             final IType type= (IType) member;
354             return type.getTypeParameter(getNewElementName());
355         } else if (member instanceof IMethod) {
356             final IMethod method= (IMethod) member;
357             return method.getTypeParameter(getNewElementName());
358         } else {
359             JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); //$NON-NLS-1$
360
Assert.isTrue(false);
361         }
362         return null;
363     }
364
365     public final String JavaDoc getProcessorName() {
366         return RefactoringCoreMessages.RenameTypeParameterProcessor_name;
367     }
368
369     public final boolean getUpdateReferences() {
370         return fUpdateReferences;
371     }
372
373     public final RefactoringStatus initialize(final RefactoringArguments arguments) {
374         if (arguments instanceof JavaRefactoringArguments) {
375             final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
376             final String JavaDoc parameter= extended.getAttribute(ATTRIBUTE_PARAMETER);
377             if (parameter == null || "".equals(parameter)) //$NON-NLS-1$
378
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PARAMETER));
379             final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
380             if (handle != null) {
381                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
382                 if (element == null || !element.exists())
383                     return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE_PARAMETER);
384                 else {
385                     if (element instanceof IMethod)
386                         fTypeParameter= ((IMethod) element).getTypeParameter(parameter);
387                     else if (element instanceof IType)
388                         fTypeParameter= ((IType) element).getTypeParameter(parameter);
389                     else
390                         return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object JavaDoc[] { handle, JDTRefactoringDescriptor.ATTRIBUTE_INPUT}));
391                     if (fTypeParameter == null || !fTypeParameter.exists())
392                         return ScriptableRefactoring.createInputFatalStatus(fTypeParameter, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE_PARAMETER);
393                 }
394             } else
395                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
396             final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
397             if (name != null && !"".equals(name)) //$NON-NLS-1$
398
setNewElementName(name);
399             else
400                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
401             final String JavaDoc references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES);
402             if (references != null) {
403                 fUpdateReferences= Boolean.valueOf(references).booleanValue();
404             } else
405                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES));
406         } else
407             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
408         return new RefactoringStatus();
409     }
410
411     public final boolean isApplicable() throws CoreException {
412         return RefactoringAvailabilityTester.isRenameAvailable(fTypeParameter);
413     }
414
415     public final void setUpdateReferences(final boolean update) {
416         fUpdateReferences= update;
417     }
418 }
419
Popular Tags