KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.util.Arrays JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.SubProgressMonitor;
22
23 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
24 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
25 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
26 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
27 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
28
29 import org.eclipse.jdt.core.IMethod;
30 import org.eclipse.jdt.core.IType;
31 import org.eclipse.jdt.core.ITypeHierarchy;
32 import org.eclipse.jdt.core.JavaModelException;
33 import org.eclipse.jdt.core.Signature;
34
35 import org.eclipse.jdt.internal.corext.refactoring.Checks;
36 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
37 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
38 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
39 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
40 import org.eclipse.jdt.internal.corext.util.JdtFlags;
41 import org.eclipse.jdt.internal.corext.util.Messages;
42
43
44 public class RenameVirtualMethodProcessor extends RenameMethodProcessor {
45     
46     private IMethod fOriginalMethod;
47     private boolean fActivationChecked;
48     private ITypeHierarchy fCachedHierarchy= null;
49     
50     /**
51      * Creates a new rename method processor.
52      * @param method the method, or <code>null</code> if invoked by scripting
53      */

54     public RenameVirtualMethodProcessor(IMethod method) {
55         super(method);
56         fOriginalMethod= getMethod();
57     }
58     
59     /*
60      * int. not javadoc'd
61      *
62      * Protected constructor; only called from RenameTypeProcessor. Initializes
63      * the method processor with an already resolved top level and ripple
64      * methods.
65      *
66      */

67     RenameVirtualMethodProcessor(IMethod topLevel, IMethod[] ripples, TextChangeManager changeManager, ITypeHierarchy hierarchy, GroupCategorySet categorySet) {
68         super(topLevel, changeManager, categorySet);
69         fOriginalMethod= getMethod();
70         fActivationChecked= true; // is top level
71
fCachedHierarchy= hierarchy; // may be null
72
setMethodsToRename(ripples);
73     }
74
75     public IMethod getOriginalMethod() {
76         return fOriginalMethod;
77     }
78
79     private ITypeHierarchy getCachedHierarchy(IType declaring, IProgressMonitor monitor) throws JavaModelException {
80         if (fCachedHierarchy != null && declaring.equals(fCachedHierarchy.getType()))
81             return fCachedHierarchy;
82         fCachedHierarchy= declaring.newTypeHierarchy(new SubProgressMonitor(monitor, 1));
83         return fCachedHierarchy;
84     }
85
86     public boolean isApplicable() throws CoreException {
87         return RefactoringAvailabilityTester.isRenameVirtualMethodAvailable(getMethod());
88     }
89     
90     //------------ preconditions -------------
91

92     public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
93         RefactoringStatus result= super.checkInitialConditions(monitor);
94         if (result.hasFatalError())
95             return result;
96         try{
97             monitor.beginTask("", 3); //$NON-NLS-1$
98
if (!fActivationChecked) {
99                 // the following code may change the method to be changed.
100
IMethod method= getMethod();
101                 fOriginalMethod= method;
102                 
103                 ITypeHierarchy hierarchy= null;
104                 IType declaringType= method.getDeclaringType();
105                 if (!declaringType.isInterface())
106                     hierarchy= getCachedHierarchy(declaringType, new SubProgressMonitor(monitor, 1));
107
108                 IMethod topmost= getMethod();
109                 if (MethodChecks.isVirtual(topmost))
110                     topmost= MethodChecks.getTopmostMethod(getMethod(), hierarchy, monitor);
111                 if (topmost != null)
112                     initialize(topmost);
113                 fActivationChecked= true;
114             }
115         } finally{
116             monitor.done();
117         }
118         return result;
119     }
120
121     protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext checkContext) throws CoreException {
122         try{
123             pm.beginTask("", 9); //$NON-NLS-1$
124
RefactoringStatus result= new RefactoringStatus();
125
126             result.merge(super.doCheckFinalConditions(new SubProgressMonitor(pm, 7), checkContext));
127             if (result.hasFatalError())
128                 return result;
129
130             final IMethod method= getMethod();
131             final IType declaring= method.getDeclaringType();
132             final ITypeHierarchy hierarchy= getCachedHierarchy(declaring, new SubProgressMonitor(pm, 1));
133             final String JavaDoc name= getNewElementName();
134             if (declaring.isInterface()) {
135                 if (isSpecialCase())
136                     result.addError(RefactoringCoreMessages.RenameMethodInInterfaceRefactoring_special_case);
137                 pm.worked(1);
138                 IMethod[] relatedMethods= relatedTypeDeclaresMethodName(new SubProgressMonitor(pm, 1), method, name);
139                 for (int i= 0; i < relatedMethods.length; i++) {
140                     IMethod relatedMethod= relatedMethods[i];
141                     RefactoringStatusContext context= JavaStatusContext.create(relatedMethod);
142                     result.addError(RefactoringCoreMessages.RenameMethodInInterfaceRefactoring_already_defined, context);
143                 }
144             } else {
145                 if (classesDeclareOverridingNativeMethod(hierarchy.getAllSubtypes(declaring))) {
146                     result.addError(Messages.format(
147                         RefactoringCoreMessages.RenameVirtualMethodRefactoring_requieres_renaming_native,
148                         new String JavaDoc[]{method.getElementName(), "UnsatisfiedLinkError"})); //$NON-NLS-1$
149
}
150     
151                 IMethod[] hierarchyMethods= hierarchyDeclaresMethodName(new SubProgressMonitor(pm, 1), hierarchy, method, name);
152                 for (int i= 0; i < hierarchyMethods.length; i++) {
153                     IMethod hierarchyMethod= hierarchyMethods[i];
154                     RefactoringStatusContext context= JavaStatusContext.create(hierarchyMethod);
155                     if (Checks.compareParamTypes(method.getParameterTypes(), hierarchyMethod.getParameterTypes())) {
156                         result.addError(Messages.format(
157                             RefactoringCoreMessages.RenameVirtualMethodRefactoring_hierarchy_declares2,
158                             name), context);
159                     } else {
160                         result.addWarning(Messages.format(
161                             RefactoringCoreMessages.RenameVirtualMethodRefactoring_hierarchy_declares1,
162                             name), context);
163                     }
164                 }
165             }
166             fCachedHierarchy= null;
167             return result;
168         } finally{
169             pm.done();
170         }
171     }
172     
173     //---- Interface checks -------------------------------------
174

175     private IMethod[] relatedTypeDeclaresMethodName(IProgressMonitor pm, IMethod method, String JavaDoc newName) throws CoreException {
176         try{
177             Set JavaDoc result= new HashSet JavaDoc();
178             Set JavaDoc types= getRelatedTypes();
179             pm.beginTask("", types.size()); //$NON-NLS-1$
180
for (Iterator JavaDoc iter= types.iterator(); iter.hasNext(); ) {
181                 final IMethod found= Checks.findMethod(method, (IType)iter.next());
182                 final IType declaring= found.getDeclaringType();
183                 result.addAll(Arrays.asList(hierarchyDeclaresMethodName(new SubProgressMonitor(pm, 1), declaring.newTypeHierarchy(new SubProgressMonitor(pm, 1)), found, newName)));
184             }
185             return (IMethod[]) result.toArray(new IMethod[result.size()]);
186         } finally {
187             pm.done();
188         }
189     }
190
191     private boolean isSpecialCase() throws CoreException {
192         String JavaDoc[] noParams= new String JavaDoc[0];
193         String JavaDoc[] specialNames= new String JavaDoc[]{"toString", "toString", "toString", "toString", "equals", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
194
"equals", "getClass", "getClass", "hashCode", "notify", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
195
"notifyAll", "wait", "wait", "wait"}; //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
196
String JavaDoc[][] specialParamTypes= new String JavaDoc[][]{noParams, noParams, noParams, noParams,
197                                                      {"QObject;"}, {"Qjava.lang.Object;"}, noParams, noParams, //$NON-NLS-2$ //$NON-NLS-1$
198
noParams, noParams, noParams, {Signature.SIG_LONG, Signature.SIG_INT},
199                                                      {Signature.SIG_LONG}, noParams};
200         String JavaDoc[] specialReturnTypes= new String JavaDoc[]{"QString;", "QString;", "Qjava.lang.String;", "Qjava.lang.String;", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
201
Signature.SIG_BOOLEAN, Signature.SIG_BOOLEAN, "QClass;", "Qjava.lang.Class;", //$NON-NLS-2$ //$NON-NLS-1$
202
Signature.SIG_INT, Signature.SIG_VOID, Signature.SIG_VOID, Signature.SIG_VOID,
203                                                    Signature.SIG_VOID, Signature.SIG_VOID};
204         Assert.isTrue((specialNames.length == specialParamTypes.length) && (specialParamTypes.length == specialReturnTypes.length));
205         for (int i= 0; i < specialNames.length; i++){
206             if (specialNames[i].equals(getNewElementName())
207                 && Checks.compareParamTypes(getMethod().getParameterTypes(), specialParamTypes[i])
208                 && !specialReturnTypes[i].equals(getMethod().getReturnType())){
209                     return true;
210             }
211         }
212         return false;
213     }
214     
215     private Set JavaDoc getRelatedTypes() {
216         Set JavaDoc methods= getMethodsToRename();
217         Set JavaDoc result= new HashSet JavaDoc(methods.size());
218         for (Iterator JavaDoc iter= methods.iterator(); iter.hasNext(); ){
219             result.add(((IMethod)iter.next()).getDeclaringType());
220         }
221         return result;
222     }
223     
224     //---- Class checks -------------------------------------
225

226     private boolean classesDeclareOverridingNativeMethod(IType[] classes) throws CoreException {
227         for (int i= 0; i < classes.length; i++){
228             IMethod[] methods= classes[i].getMethods();
229             for (int j= 0; j < methods.length; j++){
230                 if ((!methods[j].equals(getMethod()))
231                     && (JdtFlags.isNative(methods[j]))
232                     && (null != Checks.findSimilarMethod(getMethod(), new IMethod[]{methods[j]})))
233                         return true;
234             }
235         }
236         return false;
237     }
238
239     public RefactoringStatus initialize(RefactoringArguments arguments) {
240         final RefactoringStatus status= super.initialize(arguments);
241         fOriginalMethod= getMethod();
242         return status;
243     }
244
245     public String JavaDoc getDelegateUpdatingTitle(boolean plural) {
246         if (plural)
247             return RefactoringCoreMessages.DelegateMethodCreator_keep_original_renamed_plural;
248         else
249             return RefactoringCoreMessages.DelegateMethodCreator_keep_original_renamed_singular;
250     }
251 }
252
Popular Tags