1 11 package org.eclipse.jdt.internal.corext.refactoring.rename; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Set ; 19 20 import org.eclipse.text.edits.ReplaceEdit; 21 22 import org.eclipse.core.runtime.Assert; 23 import org.eclipse.core.runtime.CoreException; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.OperationCanceledException; 26 import org.eclipse.core.runtime.SubProgressMonitor; 27 28 import org.eclipse.core.resources.IFile; 29 30 import org.eclipse.ltk.core.refactoring.Change; 31 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 32 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 33 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 34 import org.eclipse.ltk.core.refactoring.TextChange; 35 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 36 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 37 import org.eclipse.ltk.core.refactoring.participants.RenameArguments; 38 39 import org.eclipse.jdt.core.Flags; 40 import org.eclipse.jdt.core.ICompilationUnit; 41 import org.eclipse.jdt.core.IJavaElement; 42 import org.eclipse.jdt.core.IJavaProject; 43 import org.eclipse.jdt.core.IMember; 44 import org.eclipse.jdt.core.IMethod; 45 import org.eclipse.jdt.core.IType; 46 import org.eclipse.jdt.core.ITypeHierarchy; 47 import org.eclipse.jdt.core.JavaConventions; 48 import org.eclipse.jdt.core.JavaCore; 49 import org.eclipse.jdt.core.JavaModelException; 50 import org.eclipse.jdt.core.WorkingCopyOwner; 51 import org.eclipse.jdt.core.dom.MethodDeclaration; 52 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; 53 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 54 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 55 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor; 56 import org.eclipse.jdt.core.search.IJavaSearchConstants; 57 import org.eclipse.jdt.core.search.IJavaSearchScope; 58 import org.eclipse.jdt.core.search.MethodDeclarationMatch; 59 import org.eclipse.jdt.core.search.SearchEngine; 60 import org.eclipse.jdt.core.search.SearchMatch; 61 import org.eclipse.jdt.core.search.SearchParticipant; 62 import org.eclipse.jdt.core.search.SearchPattern; 63 import org.eclipse.jdt.core.search.SearchRequestor; 64 65 import org.eclipse.jdt.internal.corext.refactoring.Checks; 66 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 67 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 68 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 69 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 70 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 71 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 72 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 73 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 74 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 75 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 76 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; 77 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 78 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateCreator; 79 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator; 80 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; 81 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; 82 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; 83 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating; 84 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating; 85 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 86 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 87 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 88 import org.eclipse.jdt.internal.corext.util.JdtFlags; 89 import org.eclipse.jdt.internal.corext.util.Messages; 90 import org.eclipse.jdt.internal.corext.util.SearchUtils; 91 92 import org.eclipse.jdt.ui.JavaElementLabels; 93 94 import org.eclipse.jdt.internal.ui.JavaPlugin; 95 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper; 96 97 public abstract class RenameMethodProcessor extends JavaRenameProcessor implements IReferenceUpdating, IDelegateUpdating { 98 99 private static final String ATTRIBUTE_DELEGATE= "delegate"; private static final String ATTRIBUTE_DEPRECATE= "deprecate"; 102 private SearchResultGroup[] fOccurrences; 103 private boolean fUpdateReferences; 104 private IMethod fMethod; 105 private Set fMethodsToRename; 106 private TextChangeManager fChangeManager; 107 private WorkingCopyOwner fWorkingCopyOwner; 108 private boolean fIsComposite; 109 private GroupCategorySet fCategorySet; 110 private boolean fDelegateUpdating; 111 private boolean fDelegateDeprecation; 112 protected boolean fInitialized= false; 113 114 public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameMethodProcessor"; 116 120 protected RenameMethodProcessor(IMethod method) { 121 this(method, new TextChangeManager(true), null); 122 fIsComposite= false; 123 } 124 125 135 protected RenameMethodProcessor(IMethod method, TextChangeManager manager, GroupCategorySet categorySet) { 136 initialize(method); 137 fChangeManager= manager; 138 fCategorySet= categorySet; 139 fDelegateUpdating= false; 140 fDelegateDeprecation= true; 141 fIsComposite= true; 142 } 143 144 protected void initialize(IMethod method) { 145 fMethod= method; 146 if (!fInitialized) { 147 if (method != null) 148 setNewElementName(method.getElementName()); 149 fUpdateReferences= true; 150 initializeWorkingCopyOwner(); 151 } 152 } 153 154 protected void initializeWorkingCopyOwner() { 155 fWorkingCopyOwner= new WorkingCopyOwner() {}; 156 } 157 158 protected void setData(RenameMethodProcessor other) { 159 fUpdateReferences= other.fUpdateReferences; 160 setNewElementName(other.getNewElementName()); 161 } 162 163 public String getIdentifier() { 164 return IDENTIFIER; 165 } 166 167 public boolean isApplicable() throws CoreException { 168 return RefactoringAvailabilityTester.isRenameAvailable(fMethod); 169 } 170 171 public String getProcessorName() { 172 return RefactoringCoreMessages.RenameMethodRefactoring_name; 173 } 174 175 protected String [] getAffectedProjectNatures() throws CoreException { 176 return JavaProcessors.computeAffectedNatures(fMethod); 177 } 178 179 public Object [] getElements() { 180 return new Object [] {fMethod}; 181 } 182 183 protected RenameModifications computeRenameModifications() throws CoreException { 184 RenameModifications result= new RenameModifications(); 185 RenameArguments args= new RenameArguments(getNewElementName(), getUpdateReferences()); 186 for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext();) { 187 IMethod method= (IMethod) iter.next(); 188 result.rename(method, args); 189 } 190 return result; 191 } 192 193 protected IFile[] getChangedFiles() throws CoreException { 194 return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()); 195 } 196 197 public int getSaveMode() { 198 return RefactoringSaveHelper.SAVE_NON_JAVA_UPDATES; 199 } 200 201 203 public final String getCurrentElementName(){ 204 return fMethod.getElementName(); 205 } 206 207 public final RefactoringStatus checkNewElementName(String newName) { 208 Assert.isNotNull(newName, "new name"); 210 RefactoringStatus status= Checks.checkName(newName, JavaConventions.validateMethodName(newName)); 211 if (status.isOK() && Checks.startsWithUpperCase(newName)) 212 status= RefactoringStatus.createWarningStatus(fIsComposite 213 ? Messages.format(RefactoringCoreMessages.Checks_method_names_lowercase2, new String [] { newName, fMethod.getDeclaringType().getElementName()}) 214 : RefactoringCoreMessages.Checks_method_names_lowercase); 215 216 if (Checks.isAlreadyNamed(fMethod, newName)) 217 status.addFatalError(fIsComposite 218 ? Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_same_name2, new String [] { newName, fMethod.getDeclaringType().getElementName() } ) 219 : RefactoringCoreMessages.RenameMethodRefactoring_same_name, 220 JavaStatusContext.create(fMethod)); 221 return status; 222 } 223 224 public Object getNewElement() { 225 return fMethod.getDeclaringType().getMethod(getNewElementName(), fMethod.getParameterTypes()); 226 } 227 228 public final IMethod getMethod() { 229 return fMethod; 230 } 231 232 private void initializeMethodsToRename(IProgressMonitor pm) throws CoreException { 233 if (fMethodsToRename == null) 234 fMethodsToRename= new HashSet (Arrays.asList(MethodChecks.getOverriddenMethods(getMethod(), pm))); 235 } 236 237 protected void setMethodsToRename(IMethod[] methods) { 238 fMethodsToRename= new HashSet (Arrays.asList(methods)); 239 } 240 241 protected Set getMethodsToRename() { 242 return fMethodsToRename; 243 } 244 245 247 public boolean canEnableUpdateReferences() { 248 return true; 249 } 250 251 public final void setUpdateReferences(boolean update) { 252 fUpdateReferences= update; 253 } 254 255 public boolean getUpdateReferences() { 256 return fUpdateReferences; 257 } 258 259 261 public boolean canEnableDelegateUpdating() { 262 return true; 263 } 264 265 public boolean getDelegateUpdating() { 266 return fDelegateUpdating; 267 } 268 269 public void setDelegateUpdating(boolean updating) { 270 fDelegateUpdating= updating; 271 } 272 273 public boolean getDeprecateDelegates() { 274 return fDelegateDeprecation; 275 } 276 277 public void setDeprecateDelegates(boolean deprecate) { 278 fDelegateDeprecation= deprecate; 279 } 280 281 283 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { 284 if (! fMethod.exists()){ 285 String message= Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_deleted, 286 fMethod.getCompilationUnit().getElementName()); 287 return RefactoringStatus.createFatalErrorStatus(message); 288 } 289 290 RefactoringStatus result= Checks.checkAvailability(fMethod); 291 if (result.hasFatalError()) 292 return result; 293 result.merge(Checks.checkIfCuBroken(fMethod)); 294 if (JdtFlags.isNative(fMethod)) 295 result.addError(RefactoringCoreMessages.RenameMethodRefactoring_no_native); 296 return result; 297 } 298 299 protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException { 300 try{ 301 RefactoringStatus result= new RefactoringStatus(); 302 pm.beginTask("", 9); if (!Checks.isAvailable(fMethod)) { 305 result.addFatalError(RefactoringCoreMessages.RenameMethodProcessor_is_binary, JavaStatusContext.create(fMethod)); 306 return result; 307 } 308 result.merge(Checks.checkIfCuBroken(fMethod)); 309 if (result.hasFatalError()) 310 return result; 311 pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions); 312 result.merge(checkNewElementName(getNewElementName())); 313 if (result.hasFatalError()) 314 return result; 315 316 boolean mustAnalyzeShadowing; 317 IMethod[] newNameMethods= searchForDeclarationsOfClashingMethods(new SubProgressMonitor(pm, 1)); 318 if (newNameMethods.length == 0) { 319 mustAnalyzeShadowing= false; 320 pm.worked(1); 321 } else { 322 IType[] outerTypes= searchForOuterTypesOfReferences(newNameMethods, new SubProgressMonitor(pm, 1)); 323 if (outerTypes.length > 0) { 324 mustAnalyzeShadowing= true; 333 334 } else { 335 boolean hasOldRefsInInnerTypes= true; 336 if (hasOldRefsInInnerTypes) { 342 mustAnalyzeShadowing= true; 351 } else { 352 mustAnalyzeShadowing= false; 353 } 354 } 355 } 356 357 initializeMethodsToRename(new SubProgressMonitor(pm, 1)); 358 pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_searchingForReferences); 359 fOccurrences= getOccurrences(new SubProgressMonitor(pm, 3), result); 360 pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions); 361 362 if (fUpdateReferences) 363 result.merge(checkRelatedMethods()); 364 365 result.merge(analyzeCompilationUnits()); pm.worked(1); 367 368 if (result.hasFatalError()) 369 return result; 370 371 createChanges(new SubProgressMonitor(pm, 1), result); 372 if (fUpdateReferences & mustAnalyzeShadowing) 373 result.merge(analyzeRenameChanges(new SubProgressMonitor(pm, 1))); 374 else 375 pm.worked(1); 376 377 return result; 378 } finally{ 379 pm.done(); 380 } 381 } 382 383 private IType[] searchForOuterTypesOfReferences(IMethod[] newNameMethods, IProgressMonitor pm) throws CoreException { 384 final Set outerTypesOfReferences= new HashSet (); 385 SearchPattern pattern= RefactoringSearchEngine.createOrPattern(newNameMethods, IJavaSearchConstants.REFERENCES); 386 IJavaSearchScope scope= createRefactoringScope(getMethod()); 387 SearchRequestor requestor= new SearchRequestor() { 388 public void acceptSearchMatch(SearchMatch match) throws CoreException { 389 IMember member= (IMember) match.getElement(); 390 IType declaring= member.getDeclaringType(); 391 if (declaring == null) 392 return; 393 IType outer= declaring.getDeclaringType(); 394 if (outer != null) 395 outerTypesOfReferences.add(declaring); 396 } 397 }; 398 new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), 399 scope, requestor, pm); 400 return (IType[]) outerTypesOfReferences.toArray(new IType[outerTypesOfReferences.size()]); 401 } 402 403 private IMethod[] searchForDeclarationsOfClashingMethods(IProgressMonitor pm) throws CoreException { 404 final List results= new ArrayList (); 405 SearchPattern pattern= createNewMethodPattern(); 406 IJavaSearchScope scope= RefactoringScopeFactory.create(getMethod().getJavaProject()); 407 SearchRequestor requestor= new SearchRequestor() { 408 public void acceptSearchMatch(SearchMatch match) throws CoreException { 409 Object method= match.getElement(); 410 if (method instanceof IMethod) results.add(method); 412 else 413 JavaPlugin.logErrorMessage("Unexpected element in search match: " + match.toString()); } 415 }; 416 new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, pm); 417 return (IMethod[]) results.toArray(new IMethod[results.size()]); 418 } 419 420 private SearchPattern createNewMethodPattern() throws JavaModelException { 421 StringBuffer stringPattern= new StringBuffer (getNewElementName()).append('('); 422 int paramCount= getMethod().getNumberOfParameters(); 423 for (int i= 0; i < paramCount; i++) { 424 if (i > 0) 425 stringPattern.append(','); 426 stringPattern.append('*'); 427 } 428 stringPattern.append(')'); 429 430 return SearchPattern.createPattern(stringPattern.toString(), IJavaSearchConstants.METHOD, 431 IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); 432 } 433 434 protected final IJavaSearchScope createRefactoringScope() throws CoreException { 435 return createRefactoringScope(fMethod); 436 } 437 protected static final IJavaSearchScope createRefactoringScope(IMethod method) throws CoreException { 439 return RefactoringScopeFactory.create(method); 440 } 441 442 SearchPattern createOccurrenceSearchPattern() { 443 HashSet methods= new HashSet (fMethodsToRename); 444 methods.add(fMethod); 445 IMethod[] ms= (IMethod[]) methods.toArray(new IMethod[methods.size()]); 446 return RefactoringSearchEngine.createOrPattern(ms, IJavaSearchConstants.ALL_OCCURRENCES); 447 } 448 449 SearchResultGroup[] getOccurrences(){ 450 return fOccurrences; 451 } 452 453 456 protected SearchResultGroup[] getOccurrences(IProgressMonitor pm, RefactoringStatus status) throws CoreException { 457 SearchPattern pattern= createOccurrenceSearchPattern(); 458 return RefactoringSearchEngine.search(pattern, createRefactoringScope(), 459 new MethodOccurenceCollector(getMethod().getElementName()), pm, status); 460 } 461 462 private RefactoringStatus checkRelatedMethods() throws CoreException { 463 RefactoringStatus result= new RefactoringStatus(); 464 for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext(); ) { 465 IMethod method= (IMethod)iter.next(); 466 467 result.merge(Checks.checkIfConstructorName(method, getNewElementName(), method.getDeclaringType().getElementName())); 468 469 String [] msgData= new String []{method.getElementName(), JavaModelUtil.getFullyQualifiedName(method.getDeclaringType())}; 470 if (! method.exists()){ 471 result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_not_in_model, msgData)); 472 continue; 473 } 474 if (method.isBinary()) 475 result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_binary, msgData)); 476 if (method.isReadOnly()) 477 result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_read_only, msgData)); 478 if (JdtFlags.isNative(method)) 479 result.addError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_native_1, msgData)); 480 } 481 return result; 482 } 483 484 private RefactoringStatus analyzeCompilationUnits() throws CoreException { 485 if (fOccurrences.length == 0) 486 return null; 487 488 RefactoringStatus result= new RefactoringStatus(); 489 fOccurrences= Checks.excludeCompilationUnits(fOccurrences, result); 490 if (result.hasFatalError()) 491 return result; 492 493 result.merge(Checks.checkCompileErrorsInAffectedFiles(fOccurrences)); 494 495 return result; 496 } 497 498 500 private RefactoringStatus analyzeRenameChanges(IProgressMonitor pm) throws CoreException { 501 ICompilationUnit[] newDeclarationWCs= null; 502 try { 503 pm.beginTask("", 4); RefactoringStatus result= new RefactoringStatus(); 505 ICompilationUnit[] declarationCUs= getDeclarationCUs(); 506 newDeclarationWCs= RenameAnalyzeUtil.createNewWorkingCopies(declarationCUs, 507 fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1)); 508 509 IMethod[] wcOldMethods= new IMethod[fMethodsToRename.size()]; 510 IMethod[] wcNewMethods= new IMethod[fMethodsToRename.size()]; 511 int i= 0; 512 for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext(); i++) { 513 IMethod method= (IMethod) iter.next(); 514 ICompilationUnit newCu= RenameAnalyzeUtil.findWorkingCopyForCu(newDeclarationWCs, method.getCompilationUnit()); 515 IType typeWc= (IType) JavaModelUtil.findInCompilationUnit(newCu, method.getDeclaringType()); 516 if (typeWc == null) 517 continue; 518 wcOldMethods[i]= getMethodInWorkingCopy(method, getCurrentElementName(), typeWc); 519 wcNewMethods[i]= getMethodInWorkingCopy(method, getNewElementName(), typeWc); 520 } 521 522 SearchResultGroup[] newOccurrences= batchFindNewOccurrences(wcNewMethods, wcOldMethods, newDeclarationWCs, new SubProgressMonitor(pm, 3), result); 524 525 result.merge(RenameAnalyzeUtil.analyzeRenameChanges2(fChangeManager, fOccurrences, newOccurrences, getNewElementName())); 526 return result; 527 } finally{ 528 pm.done(); 529 if (newDeclarationWCs != null){ 530 for (int i= 0; i < newDeclarationWCs.length; i++) { 531 newDeclarationWCs[i].discardWorkingCopy(); 532 } 533 } 534 } 535 } 536 537 570 private SearchResultGroup[] batchFindNewOccurrences(IMethod[] wcNewMethods, final IMethod[] wcOldMethods, ICompilationUnit[] newDeclarationWCs, IProgressMonitor pm, RefactoringStatus status) throws CoreException { 571 pm.beginTask("", 2); 573 SearchPattern refsPattern= RefactoringSearchEngine.createOrPattern(wcNewMethods, IJavaSearchConstants.REFERENCES); 574 SearchParticipant[] searchParticipants= SearchUtils.getDefaultSearchParticipants(); 575 IJavaSearchScope scope= RefactoringScopeFactory.create(wcNewMethods); 576 577 MethodOccurenceCollector requestor; 578 if (getDelegateUpdating()) { 579 requestor= new MethodOccurenceCollector(getNewElementName()) { 584 public void acceptSearchMatch(ICompilationUnit unit, SearchMatch match) throws CoreException { 585 for (int i= 0; i < wcOldMethods.length; i++) 586 if (wcOldMethods[i].equals(match.getElement())) 587 return; 588 super.acceptSearchMatch(unit, match); 589 } 590 }; 591 } else 592 requestor= new MethodOccurenceCollector(getNewElementName()); 593 594 SearchEngine searchEngine= new SearchEngine(fWorkingCopyOwner); 595 596 ArrayList needWCs= new ArrayList (); 597 HashSet declaringCUs= new HashSet (newDeclarationWCs.length); 598 for (int i= 0; i < newDeclarationWCs.length; i++) 599 declaringCUs.add(newDeclarationWCs[i].getPrimary()); 600 for (int i= 0; i < fOccurrences.length; i++) { 601 ICompilationUnit cu= fOccurrences[i].getCompilationUnit(); 602 if (! declaringCUs.contains(cu)) 603 needWCs.add(cu); 604 } 605 ICompilationUnit[] otherWCs= null; 606 try { 607 otherWCs= RenameAnalyzeUtil.createNewWorkingCopies( 608 (ICompilationUnit[]) needWCs.toArray(new ICompilationUnit[needWCs.size()]), 609 fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1)); 610 searchEngine.search(refsPattern, searchParticipants, scope, requestor, new SubProgressMonitor(pm, 1)); 611 } finally { 612 pm.done(); 613 if (otherWCs != null) { 614 for (int i= 0; i < otherWCs.length; i++) { 615 otherWCs[i].discardWorkingCopy(); 616 } 617 } 618 } 619 SearchResultGroup[] newResults= RefactoringSearchEngine.groupByCu(requestor.getResults(), status); 620 return newResults; 621 } 622 623 private ICompilationUnit[] getDeclarationCUs() { 624 Set cus= new HashSet (); 625 for (Iterator iter= fMethodsToRename.iterator(); iter.hasNext();) { 626 IMethod method= (IMethod) iter.next(); 627 cus.add(method.getCompilationUnit()); 628 } 629 return (ICompilationUnit[]) cus.toArray(new ICompilationUnit[cus.size()]); 630 } 631 632 private IMethod getMethodInWorkingCopy(IMethod method, String elementName, IType typeWc) throws CoreException{ 633 String [] paramTypeSignatures= method.getParameterTypes(); 634 return typeWc.getMethod(elementName, paramTypeSignatures); 635 } 636 637 private static IMethod[] classesDeclareMethodName(ITypeHierarchy hier, List classes, IMethod method, String newName) throws CoreException { 639 Set result= new HashSet (); 640 IType type= method.getDeclaringType(); 641 List subtypes= Arrays.asList(hier.getAllSubtypes(type)); 642 643 int parameterCount= method.getParameterTypes().length; 644 boolean isMethodPrivate= JdtFlags.isPrivate(method); 645 646 for (Iterator iter= classes.iterator(); iter.hasNext(); ){ 647 IType clazz= (IType) iter.next(); 648 IMethod[] methods= clazz.getMethods(); 649 boolean isSubclass= subtypes.contains(clazz); 650 for (int j= 0; j < methods.length; j++) { 651 IMethod foundMethod= Checks.findMethod(newName, parameterCount, false, new IMethod[] {methods[j]}); 652 if (foundMethod == null) 653 continue; 654 if (isSubclass || type.equals(clazz)) 655 result.add(foundMethod); 656 else if ((! isMethodPrivate) && (! JdtFlags.isPrivate(methods[j]))) 657 result.add(foundMethod); 658 } 659 } 660 return (IMethod[]) result.toArray(new IMethod[result.size()]); 661 } 662 663 final static IMethod[] hierarchyDeclaresMethodName(IProgressMonitor pm, ITypeHierarchy hierarchy, IMethod method, String newName) throws CoreException { 664 Set result= new HashSet (); 665 IType type= method.getDeclaringType(); 666 IMethod foundMethod= Checks.findMethod(newName, method.getParameterTypes().length, false, type); 667 if (foundMethod != null) 668 result.add(foundMethod); 669 670 IMethod[] foundInHierarchyClasses= classesDeclareMethodName(hierarchy, Arrays.asList(hierarchy.getAllClasses()), method, newName); 671 if (foundInHierarchyClasses != null) 672 result.addAll(Arrays.asList(foundInHierarchyClasses)); 673 674 IType[] implementingClasses= hierarchy.getImplementingClasses(type); 675 IMethod[] foundInImplementingClasses= classesDeclareMethodName(hierarchy, Arrays.asList(implementingClasses), method, newName); 676 if (foundInImplementingClasses != null) 677 result.addAll(Arrays.asList(foundInImplementingClasses)); 678 return (IMethod[]) result.toArray(new IMethod[result.size()]); 679 } 680 681 public Change createChange(IProgressMonitor monitor) throws CoreException { 682 try { 683 final TextChange[] changes= fChangeManager.getAllChanges(); 684 final List list= new ArrayList (changes.length); 685 list.addAll(Arrays.asList(changes)); 686 String project= null; 687 IJavaProject javaProject= fMethod.getJavaProject(); 688 if (javaProject != null) 689 project= javaProject.getElementName(); 690 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE; 691 try { 692 if (!Flags.isPrivate(fMethod.getFlags())) 693 flags|= RefactoringDescriptor.MULTI_CHANGE; 694 } catch (JavaModelException exception) { 695 JavaPlugin.log(exception); 696 } 697 final IType declaring= fMethod.getDeclaringType(); 698 try { 699 if (declaring.isAnonymous() || declaring.isLocal()) 700 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 701 } catch (JavaModelException exception) { 702 JavaPlugin.log(exception); 703 } 704 final String description= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description_short, fMethod.getElementName()); 705 final String header= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description, new String [] { JavaElementLabels.getTextLabel(fMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()}); 706 final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString(); 707 final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_METHOD); 708 descriptor.setProject(project); 709 descriptor.setDescription(description); 710 descriptor.setComment(comment); 711 descriptor.setFlags(flags); 712 descriptor.setJavaElement(fMethod); 713 descriptor.setNewName(getNewElementName()); 714 descriptor.setUpdateReferences(fUpdateReferences); 715 descriptor.setKeepOriginal(fDelegateUpdating); 716 descriptor.setDeprecateDelegate(fDelegateDeprecation); 717 return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameMethodProcessor_change_name, (Change[]) list.toArray(new Change[list.size()])); 718 } finally { 719 monitor.done(); 720 } 721 } 722 723 private TextChangeManager createChanges(IProgressMonitor pm, RefactoringStatus status) throws CoreException { 724 if (!fIsComposite) 725 fChangeManager.clear(); 726 addOccurrences(fChangeManager, pm, status); 727 return fChangeManager; 728 } 729 730 void addOccurrences(TextChangeManager manager, IProgressMonitor pm, RefactoringStatus status) throws CoreException{ 731 pm.beginTask("", fOccurrences.length); for (int i= 0; i < fOccurrences.length; i++){ 733 ICompilationUnit cu= fOccurrences[i].getCompilationUnit(); 734 if (cu == null) 735 continue; 736 737 SearchMatch[] results= fOccurrences[i].getSearchResults(); 738 739 741 List declarationsInThisCu= new ArrayList (); 742 List referencesInThisCu= new ArrayList (); 743 744 for (int j= 0; j < results.length; j++) { 745 if (results[j] instanceof MethodDeclarationMatch) 746 declarationsInThisCu.add(results[j]); 747 else 748 referencesInThisCu.add(results[j]); 749 } 750 751 if (declarationsInThisCu.size() > 0) { 753 754 if (fDelegateUpdating) { 755 CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu); 757 rewrite.setResolveBindings(true); 758 759 for (Iterator iter= declarationsInThisCu.iterator(); iter.hasNext();) { 760 SearchMatch element= (SearchMatch) iter.next(); 761 MethodDeclaration method= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) element.getElement(), rewrite.getRoot()); 762 DelegateCreator creator= new DelegateMethodCreator(); 763 creator.setDeclareDeprecated(fDelegateDeprecation); 764 creator.setDeclaration(method); 765 creator.setSourceRewrite(rewrite); 766 creator.setNewElementName(getNewElementName()); 767 creator.prepareDelegate(); 768 creator.createEdit(); 769 } 770 TextChange changeForThisCu= rewrite.createChange(); 773 changeForThisCu.setKeepPreviewEdits(true); 774 manager.manage(cu, changeForThisCu); 775 } 776 777 for (Iterator iter= declarationsInThisCu.iterator(); iter.hasNext();) { 779 SearchMatch element= (SearchMatch) iter.next(); 780 simpleUpdate(element, cu, manager.get(cu)); 781 } 782 } 783 784 if (fUpdateReferences) { 786 for (Iterator iter= referencesInThisCu.iterator(); iter.hasNext();) { 787 SearchMatch element= (SearchMatch) iter.next(); 788 simpleUpdate(element, cu, manager.get(cu)); 789 } 790 } 791 792 pm.worked(1); 793 if (pm.isCanceled()) 794 throw new OperationCanceledException(); 795 } 796 pm.done(); 797 } 798 799 private void simpleUpdate(SearchMatch element, ICompilationUnit cu, TextChange textChange) { 800 String editName= RefactoringCoreMessages.RenameMethodRefactoring_update_occurrence; 801 ReplaceEdit replaceEdit= createReplaceEdit(element, cu); 802 addTextEdit(textChange, editName, replaceEdit); 803 } 804 805 protected final ReplaceEdit createReplaceEdit(SearchMatch searchResult, ICompilationUnit cu) { 806 if (searchResult.isImplicit()) { StringBuffer sb= new StringBuffer (getNewElementName()); 808 if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, true))) 809 sb.append(' '); 810 sb.append('='); 811 if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, true))) 812 sb.append(' '); 813 return new ReplaceEdit(searchResult.getOffset(), 0, sb.toString()); 814 } else { 815 return new ReplaceEdit(searchResult.getOffset(), searchResult.getLength(), getNewElementName()); 816 } 817 } 818 819 public RefactoringStatus initialize(RefactoringArguments arguments) { 820 if (arguments instanceof JavaRefactoringArguments) { 821 fInitialized= true; 822 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 823 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 824 if (handle != null) { 825 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 826 final String refactoring= getRefactoring().getName(); 827 if (element instanceof IMethod) { 828 final IMethod method= (IMethod) element; 829 final IType declaring= method.getDeclaringType(); 830 if (declaring != null && declaring.exists()) { 831 final IMethod[] methods= declaring.findMethods(method); 832 if (methods != null && methods.length == 1 && methods[0] != null) { 833 if (!methods[0].exists()) 834 return ScriptableRefactoring.createInputFatalStatus(methods[0], refactoring, IJavaRefactorings.RENAME_METHOD); 835 fMethod= methods[0]; 836 initializeWorkingCopyOwner(); 837 } else 838 return ScriptableRefactoring.createInputFatalStatus(null, refactoring, IJavaRefactorings.RENAME_METHOD); 839 } else 840 return ScriptableRefactoring.createInputFatalStatus(element, refactoring, IJavaRefactorings.RENAME_METHOD); 841 } else 842 return ScriptableRefactoring.createInputFatalStatus(element, refactoring, IJavaRefactorings.RENAME_METHOD); 843 } else 844 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 845 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 846 if (name != null && !"".equals(name)) setNewElementName(name); 848 else 849 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 850 final String references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES); 851 if (references != null) { 852 fUpdateReferences= Boolean.valueOf(references).booleanValue(); 853 } else 854 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES)); 855 final String delegate= extended.getAttribute(ATTRIBUTE_DELEGATE); 856 if (delegate != null) { 857 fDelegateUpdating= Boolean.valueOf(delegate).booleanValue(); 858 } else 859 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE)); 860 final String deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE); 861 if (deprecate != null) { 862 fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue(); 863 } else 864 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE)); 865 } else 866 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 867 return new RefactoringStatus(); 868 } 869 870 protected void addTextEdit(TextChange change, String editName, ReplaceEdit replaceEdit) { 871 if (fIsComposite) 872 TextChangeCompatibility.addTextEdit(change, editName, replaceEdit, fCategorySet); 873 else 874 TextChangeCompatibility.addTextEdit(change, editName, replaceEdit); 875 876 } 877 } 878 | Popular Tags |