1 11 package org.eclipse.jdt.internal.corext.refactoring.rename; 12 13 import java.util.Arrays ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.Set ; 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 54 public RenameVirtualMethodProcessor(IMethod method) { 55 super(method); 56 fOriginalMethod= getMethod(); 57 } 58 59 67 RenameVirtualMethodProcessor(IMethod topLevel, IMethod[] ripples, TextChangeManager changeManager, ITypeHierarchy hierarchy, GroupCategorySet categorySet) { 68 super(topLevel, changeManager, categorySet); 69 fOriginalMethod= getMethod(); 70 fActivationChecked= true; fCachedHierarchy= hierarchy; 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 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); if (!fActivationChecked) { 99 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); 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 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 []{method.getElementName(), "UnsatisfiedLinkError"})); } 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 175 private IMethod[] relatedTypeDeclaresMethodName(IProgressMonitor pm, IMethod method, String newName) throws CoreException { 176 try{ 177 Set result= new HashSet (); 178 Set types= getRelatedTypes(); 179 pm.beginTask("", types.size()); for (Iterator 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 [] noParams= new String [0]; 193 String [] specialNames= new String []{"toString", "toString", "toString", "toString", "equals", "equals", "getClass", "getClass", "hashCode", "notify", "notifyAll", "wait", "wait", "wait"}; String [][] specialParamTypes= new String [][]{noParams, noParams, noParams, noParams, 197 {"QObject;"}, {"Qjava.lang.Object;"}, noParams, noParams, noParams, noParams, noParams, {Signature.SIG_LONG, Signature.SIG_INT}, 199 {Signature.SIG_LONG}, noParams}; 200 String [] specialReturnTypes= new String []{"QString;", "QString;", "Qjava.lang.String;", "Qjava.lang.String;", Signature.SIG_BOOLEAN, Signature.SIG_BOOLEAN, "QClass;", "Qjava.lang.Class;", 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 getRelatedTypes() { 216 Set methods= getMethodsToRename(); 217 Set result= new HashSet (methods.size()); 218 for (Iterator iter= methods.iterator(); iter.hasNext(); ){ 219 result.add(((IMethod)iter.next()).getDeclaringType()); 220 } 221 return result; 222 } 223 224 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 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 |