1 12 package org.eclipse.jdt.internal.corext.refactoring.rename; 13 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.LinkedHashMap ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.eclipse.text.edits.ReplaceEdit; 25 26 import org.eclipse.core.runtime.Assert; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IConfigurationElement; 29 import org.eclipse.core.runtime.IProduct; 30 import org.eclipse.core.runtime.IProgressMonitor; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.NullProgressMonitor; 33 import org.eclipse.core.runtime.OperationCanceledException; 34 import org.eclipse.core.runtime.Platform; 35 import org.eclipse.core.runtime.SubProgressMonitor; 36 37 import org.eclipse.core.resources.IContainer; 38 import org.eclipse.core.resources.IFile; 39 import org.eclipse.core.resources.IResource; 40 41 import org.eclipse.ltk.core.refactoring.Change; 42 import org.eclipse.ltk.core.refactoring.GroupCategory; 43 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 44 import org.eclipse.ltk.core.refactoring.IResourceMapper; 45 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 46 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 47 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 48 import org.eclipse.ltk.core.refactoring.TextChange; 49 import org.eclipse.ltk.core.refactoring.TextFileChange; 50 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 51 import org.eclipse.ltk.core.refactoring.participants.IParticipantDescriptorFilter; 52 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 53 import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; 54 import org.eclipse.ltk.core.refactoring.participants.RenameArguments; 55 56 import org.eclipse.jdt.core.Flags; 57 import org.eclipse.jdt.core.ICompilationUnit; 58 import org.eclipse.jdt.core.IField; 59 import org.eclipse.jdt.core.IImportDeclaration; 60 import org.eclipse.jdt.core.IJavaElement; 61 import org.eclipse.jdt.core.IJavaProject; 62 import org.eclipse.jdt.core.ILocalVariable; 63 import org.eclipse.jdt.core.IMember; 64 import org.eclipse.jdt.core.IMethod; 65 import org.eclipse.jdt.core.IPackageFragment; 66 import org.eclipse.jdt.core.ISourceRange; 67 import org.eclipse.jdt.core.IType; 68 import org.eclipse.jdt.core.ITypeHierarchy; 69 import org.eclipse.jdt.core.JavaCore; 70 import org.eclipse.jdt.core.JavaModelException; 71 import org.eclipse.jdt.core.Signature; 72 import org.eclipse.jdt.core.dom.AST; 73 import org.eclipse.jdt.core.dom.ASTVisitor; 74 import org.eclipse.jdt.core.dom.CompilationUnit; 75 import org.eclipse.jdt.core.dom.MethodDeclaration; 76 import org.eclipse.jdt.core.dom.Modifier; 77 import org.eclipse.jdt.core.dom.TypeDeclaration; 78 import org.eclipse.jdt.core.refactoring.IJavaElementMapper; 79 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 80 import org.eclipse.jdt.core.refactoring.RenameTypeArguments; 81 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 82 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor; 83 import org.eclipse.jdt.core.search.IJavaSearchConstants; 84 import org.eclipse.jdt.core.search.IJavaSearchScope; 85 import org.eclipse.jdt.core.search.SearchMatch; 86 import org.eclipse.jdt.core.search.SearchPattern; 87 import org.eclipse.jdt.core.search.TypeReferenceMatch; 88 89 import org.eclipse.jdt.internal.corext.refactoring.Checks; 90 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 91 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 92 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 93 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 94 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 95 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 96 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 97 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 98 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 99 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 100 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange; 101 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameResourceChange; 102 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; 103 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 104 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; 105 import org.eclipse.jdt.internal.corext.refactoring.tagging.IQualifiedNameUpdating; 106 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating; 107 import org.eclipse.jdt.internal.corext.refactoring.tagging.ISimilarDeclarationUpdating; 108 import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating; 109 import org.eclipse.jdt.internal.corext.refactoring.util.Changes; 110 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; 111 import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameFinder; 112 import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameSearchResult; 113 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 114 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 115 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 116 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 117 import org.eclipse.jdt.internal.corext.util.JdtFlags; 118 import org.eclipse.jdt.internal.corext.util.Messages; 119 import org.eclipse.jdt.internal.corext.util.SearchUtils; 120 121 import org.eclipse.jdt.ui.JavaElementLabels; 122 123 import org.eclipse.jdt.internal.ui.JavaPlugin; 124 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper; 125 126 public class RenameTypeProcessor extends JavaRenameProcessor implements ITextUpdating, IReferenceUpdating, IQualifiedNameUpdating, ISimilarDeclarationUpdating, IResourceMapper, IJavaElementMapper { 127 128 private static final String ATTRIBUTE_QUALIFIED= "qualified"; private static final String ATTRIBUTE_TEXTUAL_MATCHES= "textual"; private static final String ATTRIBUTE_PATTERNS= "patterns"; private static final String ATTRIBUTE_SIMILAR_DECLARATIONS= "similarDeclarations"; private static final String ATTRIBUTE_MATCHING_STRATEGY= "matchStrategy"; 134 private static final GroupCategorySet CATEGORY_TYPE_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.type", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type_description)); private static final GroupCategorySet CATEGORY_METHOD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.method", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method_description)); private static final GroupCategorySet CATEGORY_FIELD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.field", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields_description)); private static final GroupCategorySet CATEGORY_LOCAL_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.local", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables_description)); 139 private IType fType; 140 private SearchResultGroup[] fReferences; 141 private TextChangeManager fChangeManager; 142 private QualifiedNameSearchResult fQualifiedNameSearchResult; 143 144 private boolean fUpdateReferences; 145 146 private boolean fUpdateTextualMatches; 147 148 private boolean fUpdateQualifiedNames; 149 private String fFilePatterns; 150 151 public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameTypeProcessor"; 153 155 private boolean fUpdateSimilarElements; 156 private Map fFinalSimilarElementToName= null; 157 private int fRenamingStrategy; 158 159 private LinkedHashMap fPreloadedElementToName= null; 161 private Map fPreloadedElementToSelection= null; 162 private LinkedHashMap fPreloadedElementToNameDefault= null; 163 164 private String fCachedNewName= null; 167 private boolean fCachedRenameSimilarElements= false; 168 private int fCachedRenamingStrategy= -1; 169 private RefactoringStatus fCachedRefactoringStatus= null; 170 171 public static final class ParticipantDescriptorFilter implements IParticipantDescriptorFilter { 172 173 public boolean select(IConfigurationElement element, RefactoringStatus status) { 174 IConfigurationElement[] params= element.getChildren(PARAM); 175 for (int i= 0; i < params.length; i++) { 176 IConfigurationElement param= params[i]; 177 if ("handlesSimilarDeclarations".equals(param.getAttribute(NAME)) && "false".equals(param.getAttribute(VALUE))) { return false; 180 } 181 } 182 return true; 183 } 184 } 185 186 private class NoOverrideProgressMonitor extends SubProgressMonitor { 187 public NoOverrideProgressMonitor(IProgressMonitor monitor, int ticks) { 188 super(monitor, ticks, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); 189 } 190 public void setTaskName(String name) { 191 } 193 } 194 195 199 public RenameTypeProcessor(IType type) { 200 fType= type; 201 if (type != null) 202 setNewElementName(type.getElementName()); 203 fUpdateReferences= true; fUpdateTextualMatches= false; 205 fUpdateSimilarElements= false; fRenamingStrategy= RenamingNameSuggestor.STRATEGY_EXACT; 207 } 208 209 public IType getType() { 210 return fType; 211 } 212 213 public String getIdentifier() { 214 return IDENTIFIER; 215 } 216 217 public boolean isApplicable() throws CoreException { 218 return RefactoringAvailabilityTester.isRenameAvailable(fType); 219 } 220 221 public String getProcessorName() { 222 return RefactoringCoreMessages.RenameTypeRefactoring_name; 223 } 224 225 protected String [] getAffectedProjectNatures() throws CoreException { 226 return JavaProcessors.computeAffectedNatures(fType); 227 } 228 229 public Object [] getElements() { 230 return new Object [] {fType}; 231 } 232 233 protected RenameModifications computeRenameModifications() { 234 RenameModifications result= new RenameModifications(); 235 result.rename(fType, new RenameTypeArguments(getNewElementName(), getUpdateReferences(), 236 getUpdateSimilarDeclarations(), getSimilarElements()), createParticipantDescriptorFilter()); 237 if (isPrimaryType()) { 238 ICompilationUnit cu= fType.getCompilationUnit(); 239 String newCUName= getNewCompilationUnit().getElementName(); 240 result.rename(cu, new RenameArguments(newCUName, getUpdateReferences())); 241 } 242 return result; 243 } 244 245 248 private boolean isPrimaryType() { 249 String cuName= fType.getCompilationUnit().getElementName(); 250 String typeName= fType.getElementName(); 251 return Checks.isTopLevel(fType) && JavaCore.removeJavaLikeExtension(cuName).equals(typeName); 252 } 253 254 256 public String getCurrentElementName(){ 257 return fType.getElementName(); 258 } 259 260 public String getCurrentElementQualifier(){ 261 return JavaModelUtil.getTypeContainerName(fType); 262 } 263 264 public RefactoringStatus checkNewElementName(String newName){ 265 Assert.isNotNull(newName, "new name"); RefactoringStatus result= Checks.checkTypeName(newName); 267 if (Checks.isAlreadyNamed(fType, newName)) 268 result.addFatalError(RefactoringCoreMessages.RenameTypeRefactoring_choose_another_name); 269 return result; 270 } 271 272 public Object getNewElement() { 273 if (Checks.isTopLevel(fType)) { 274 return getNewCompilationUnit().getType(getNewElementName()); 275 } else { 276 return fType.getDeclaringType().getType(getNewElementName()); 277 } 278 } 279 280 private ICompilationUnit getNewCompilationUnit() { 281 ICompilationUnit cu= fType.getCompilationUnit(); 282 if (isPrimaryType()) { 283 IPackageFragment parent= fType.getPackageFragment(); 284 String renamedCUName= JavaModelUtil.getRenamedCUName(cu, getNewElementName()); 285 return parent.getCompilationUnit(renamedCUName); 286 } else { 287 return cu; 288 } 289 } 290 291 293 protected RenameArguments createRenameArguments() { 294 return new RenameTypeArguments(getNewElementName(), getUpdateReferences(), 295 getUpdateSimilarDeclarations(), getSimilarElements()); 296 } 297 298 protected IParticipantDescriptorFilter createParticipantDescriptorFilter() { 299 if (!getUpdateSimilarDeclarations()) 300 return null; 301 return new ParticipantDescriptorFilter(); 302 } 303 304 protected IFile[] getChangedFiles() throws CoreException { 305 List result= new ArrayList (); 306 result.addAll(Arrays.asList(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()))); 307 if (fQualifiedNameSearchResult != null) 308 result.addAll(Arrays.asList(fQualifiedNameSearchResult.getAllFiles())); 309 if (willRenameCU()) 310 result.add(ResourceUtil.getFile(fType.getCompilationUnit())); 311 return (IFile[]) result.toArray(new IFile[result.size()]); 312 } 313 314 public int getSaveMode() { 315 return RefactoringSaveHelper.SAVE_NON_JAVA_UPDATES; 316 } 317 318 320 public boolean canEnableTextUpdating() { 321 return true; 322 } 323 324 public boolean getUpdateTextualMatches() { 325 return fUpdateTextualMatches; 326 } 327 public void setUpdateTextualMatches(boolean update) { 328 fUpdateTextualMatches= update; 329 } 330 331 333 public void setUpdateReferences(boolean update){ 334 fUpdateReferences= update; 335 } 336 337 public boolean canEnableUpdateReferences(){ 338 return true; 339 } 340 341 public boolean getUpdateReferences(){ 342 return fUpdateReferences; 343 } 344 345 347 public boolean canEnableQualifiedNameUpdating() { 348 return !fType.getPackageFragment().isDefaultPackage() && !(fType.getParent() instanceof IType); 349 } 350 351 public boolean getUpdateQualifiedNames() { 352 return fUpdateQualifiedNames; 353 } 354 355 public void setUpdateQualifiedNames(boolean update) { 356 fUpdateQualifiedNames= update; 357 } 358 359 public String getFilePatterns() { 360 return fFilePatterns; 361 } 362 363 public void setFilePatterns(String patterns) { 364 Assert.isNotNull(patterns); 365 fFilePatterns= patterns; 366 } 367 368 370 public boolean canEnableSimilarDeclarationUpdating() { 371 372 IProduct product= Platform.getProduct(); 373 if (product != null) { 374 String property= product.getProperty("org.eclipse.jdt.ui.refactoring.handlesSimilarDeclarations"); if ("false".equalsIgnoreCase(property)) return false; 377 } 378 379 return true; 380 } 381 382 public void setUpdateSimilarDeclarations(boolean update) { 383 fUpdateSimilarElements= update; 384 } 385 386 public boolean getUpdateSimilarDeclarations() { 387 return fUpdateSimilarElements; 388 } 389 390 public int getMatchStrategy() { 391 return fRenamingStrategy; 392 393 } 394 395 public void setMatchStrategy(int selectedStrategy) { 396 fRenamingStrategy= selectedStrategy; 397 } 398 399 404 public IJavaElement[] getSimilarElements() { 405 if (fFinalSimilarElementToName == null) 406 return null; 407 Set keys= fFinalSimilarElementToName.keySet(); 408 return (IJavaElement[])keys.toArray(new IJavaElement[keys.size()]); 409 } 410 411 414 public IResource getRefactoredResource(IResource element) { 415 if (element instanceof IFile) { 416 if (Checks.isTopLevel(fType) && element.equals(fType.getResource())) 417 return getNewCompilationUnit().getResource(); 418 } 419 return element; 420 } 421 422 425 public IJavaElement getRefactoredJavaElement(IJavaElement element) { 426 if (element instanceof ICompilationUnit) { 427 if (Checks.isTopLevel(fType) && element.equals(fType.getCompilationUnit())) 428 return getNewCompilationUnit(); 429 } else if (element instanceof IMember) { 430 final IType newType= (IType) getNewElement(); 431 final RefactoringHandleTransplanter transplanter= new RefactoringHandleTransplanter(fType, newType, fFinalSimilarElementToName); 432 return transplanter.transplantHandle((IMember) element); 433 } 434 return element; 435 } 436 437 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { 438 IType primary= (IType) fType.getPrimaryElement(); 439 if (primary == null || !primary.exists()) { 440 String message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_does_not_exist, new String [] { JavaModelUtil.getFullyQualifiedName(fType), fType.getCompilationUnit().getElementName()}); 441 return RefactoringStatus.createFatalErrorStatus(message); 442 } 443 fType= primary; 444 return Checks.checkIfCuBroken(fType); 445 } 446 447 protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException { 448 Assert.isNotNull(fType, "type"); Assert.isNotNull(getNewElementName(), "newName"); RefactoringStatus result= new RefactoringStatus(); 451 452 int referenceSearchTicks= fUpdateReferences || fUpdateSimilarElements ? 15 : 0; 453 int affectedCusTicks= fUpdateReferences || fUpdateSimilarElements ? 10 : 1; 454 int similarElementTicks= fUpdateSimilarElements ? 85 : 0; 455 int createChangeTicks = 5; 456 int qualifiedNamesTicks= fUpdateQualifiedNames ? 50 : 0; 457 458 try{ 459 pm.beginTask("", 12 + referenceSearchTicks + affectedCusTicks + similarElementTicks + createChangeTicks + qualifiedNamesTicks); pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking); 461 462 fChangeManager= new TextChangeManager(true); 463 464 result.merge(checkNewElementName(getNewElementName())); 465 if (result.hasFatalError()) 466 return result; 467 result.merge(Checks.checkIfCuBroken(fType)); 468 if (result.hasFatalError()) 469 return result; 470 pm.worked(1); 471 472 result.merge(checkTypesInCompilationUnit()); 473 pm.worked(1); 474 475 result.merge(checkForMethodsWithConstructorNames()); 476 pm.worked(1); 477 478 result.merge(checkImportedTypes()); 479 pm.worked(1); 480 481 if (Checks.isTopLevel(fType) && (JdtFlags.isPublic(fType))) 482 result.merge(Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName())); 483 pm.worked(1); 484 485 if (isPrimaryType()) 486 result.merge(checkNewPathValidity()); 487 pm.worked(1); 488 489 result.merge(checkEnclosingTypes()); 490 pm.worked(1); 491 492 result.merge(checkEnclosedTypes()); 493 pm.worked(1); 494 495 result.merge(checkTypesInPackage()); 496 pm.worked(1); 497 498 result.merge(checkTypesImportedInCu()); 499 pm.worked(1); 500 501 result.merge(Checks.checkForMainAndNativeMethods(fType)); 502 pm.worked(1); 503 504 if (result.hasFatalError()) 506 return result; 507 508 result.merge(analyseEnclosedTypes()); 509 pm.worked(1); 510 if (result.hasFatalError()) 512 return result; 513 514 if (fUpdateReferences || fUpdateSimilarElements) { 516 pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_searching); 517 result.merge(initializeReferences(new SubProgressMonitor(pm, referenceSearchTicks))); 518 } else { 519 fReferences= new SearchResultGroup[0]; 520 } 521 522 pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking); 523 if (pm.isCanceled()) 524 throw new OperationCanceledException(); 525 526 if (fUpdateReferences || fUpdateSimilarElements) { 527 result.merge(analyzeAffectedCompilationUnits(new SubProgressMonitor(pm, affectedCusTicks))); 528 } else { 529 Checks.checkCompileErrorsInAffectedFile(result, fType.getResource()); 530 pm.worked(affectedCusTicks); 531 } 532 533 if (result.hasFatalError()) 534 return result; 535 536 if (fUpdateSimilarElements) { 537 result.merge(initializeSimilarElementsRenameProcessors(new SubProgressMonitor(pm, similarElementTicks), context)); 538 if (result.hasFatalError()) 539 return result; 540 } 541 542 createChanges(new SubProgressMonitor(pm, createChangeTicks)); 543 544 if (fUpdateQualifiedNames) 545 computeQualifiedNameMatches(new SubProgressMonitor(pm, qualifiedNamesTicks)); 546 547 return result; 548 } finally { 549 pm.done(); 550 } 551 } 552 553 565 public RefactoringStatus initializeReferences(IProgressMonitor monitor) throws JavaModelException, OperationCanceledException { 566 567 Assert.isNotNull(fType); 568 Assert.isNotNull(getNewElementName()); 569 570 574 if (fReferences != null && (getNewElementName().equals(fCachedNewName)) && (fCachedRenameSimilarElements == getUpdateSimilarDeclarations()) && (fCachedRenamingStrategy == fRenamingStrategy)) 575 return fCachedRefactoringStatus; 576 577 fCachedNewName= getNewElementName(); 578 fCachedRenameSimilarElements= fUpdateSimilarElements; 579 fCachedRenamingStrategy= fRenamingStrategy; 580 fCachedRefactoringStatus= new RefactoringStatus(); 581 582 583 try { 584 SearchPattern pattern= SearchPattern.createPattern(fType, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); 585 fReferences= RefactoringSearchEngine.search( 586 pattern, 587 RefactoringScopeFactory.create(fType), 588 new TypeOccurrenceCollector(fType), 589 monitor, 590 fCachedRefactoringStatus); 591 fReferences= Checks.excludeCompilationUnits(fReferences, fCachedRefactoringStatus); 592 593 fPreloadedElementToName= new LinkedHashMap (); 594 fPreloadedElementToSelection= new HashMap (); 595 596 final String unQualifiedTypeName= fType.getElementName(); 597 598 monitor.beginTask("", fReferences.length); 600 if (getUpdateSimilarDeclarations()) { 601 602 RenamingNameSuggestor sugg= new RenamingNameSuggestor(fRenamingStrategy); 603 604 for (int i= 0; i < fReferences.length; i++) { 605 final ICompilationUnit cu= fReferences[i].getCompilationUnit(); 606 if (cu == null) 607 continue; 608 609 final SearchMatch[] results= fReferences[i].getSearchResults(); 610 611 for (int j= 0; j < results.length; j++) { 612 613 if (! (results[j] instanceof TypeReferenceMatch)) 614 continue; 615 616 final TypeReferenceMatch match= (TypeReferenceMatch) results[j]; 617 final List matches= new ArrayList (); 618 619 if (match.getLocalElement() != null) 620 matches.add(match.getLocalElement()); 621 else 622 matches.add(match.getElement()); 623 624 final IJavaElement[] others= match.getOtherElements(); 625 if (others != null) 626 matches.addAll(Arrays.asList(others)); 627 628 for (Iterator iter= matches.iterator(); iter.hasNext();) { 629 final IJavaElement element= (IJavaElement) iter.next(); 630 631 if (! (element instanceof IMethod) && ! (element instanceof IField) && ! (element instanceof ILocalVariable)) 632 continue; 633 634 if (!isInDeclaredType(match.getOffset(), element)) 635 continue; 636 637 if (element instanceof IField) { 638 final IField currentField= (IField) element; 639 final String newFieldName= sugg.suggestNewFieldName(currentField.getJavaProject(), currentField.getElementName(), Flags.isStatic(currentField.getFlags()), 640 unQualifiedTypeName, getNewElementName()); 641 642 if (newFieldName != null) 643 fPreloadedElementToName.put(currentField, newFieldName); 644 } 645 646 if (element instanceof IMethod) { 647 final IMethod currentMethod= (IMethod) element; 648 addMethodRename(unQualifiedTypeName, sugg, currentMethod); 649 } 650 651 if (element instanceof ILocalVariable) { 652 final ILocalVariable currentLocal= (ILocalVariable) element; 653 final boolean isParameter; 654 655 if (JavaModelUtil.isParameter(currentLocal)) { 656 addMethodRename(unQualifiedTypeName, sugg, (IMethod) currentLocal.getParent()); 657 isParameter= true; 658 } else 659 isParameter= false; 660 661 final String newLocalName= sugg 662 .suggestNewLocalName(currentLocal.getJavaProject(), currentLocal.getElementName(), isParameter, unQualifiedTypeName, getNewElementName()); 663 664 if (newLocalName != null) 665 fPreloadedElementToName.put(currentLocal, newLocalName); 666 } 667 } 668 } 669 if (monitor.isCanceled()) 670 throw new OperationCanceledException(); 671 } 672 } 673 674 for (Iterator iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) { 675 IJavaElement element= (IJavaElement) iter.next(); 676 fPreloadedElementToSelection.put(element, Boolean.TRUE); 677 } 678 fPreloadedElementToNameDefault= (LinkedHashMap ) fPreloadedElementToName.clone(); 679 680 } catch (OperationCanceledException e) { 681 fReferences= null; 682 fPreloadedElementToName= null; 683 throw new OperationCanceledException(); 684 } 685 return fCachedRefactoringStatus; 686 } 687 688 698 private boolean isInDeclaredType(int matchOffset, IJavaElement parentElement) throws JavaModelException { 699 if (parentElement != null) { 700 int enclosingNameOffset= 0; 701 if (parentElement instanceof IMethod || parentElement instanceof IField) 702 enclosingNameOffset= ((IMember) parentElement).getNameRange().getOffset(); 703 else if (parentElement instanceof ILocalVariable) 704 enclosingNameOffset= ((ILocalVariable) parentElement).getNameRange().getOffset(); 705 706 return (matchOffset < enclosingNameOffset); 707 } 708 return false; 709 } 710 711 private void addMethodRename(final String unQualifiedTypeName, RenamingNameSuggestor sugg, final IMethod currentMethod) throws JavaModelException { 712 if (!currentMethod.isConstructor()) { 713 final String newMethodName= sugg.suggestNewMethodName(currentMethod.getElementName(), unQualifiedTypeName, getNewElementName()); 714 715 if (newMethodName != null) 716 fPreloadedElementToName.put(currentMethod, newMethodName); 717 } 718 } 719 720 private RefactoringStatus checkNewPathValidity() { 721 IContainer c= fType.getCompilationUnit().getResource().getParent(); 722 723 String notRename= RefactoringCoreMessages.RenameTypeRefactoring_will_not_rename; 724 IStatus status= c.getWorkspace().validateName(getNewElementName(), IResource.FILE); 725 if (status.getSeverity() == IStatus.ERROR) 726 return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); 728 status= c.getWorkspace().validatePath(createNewPath(getNewElementName()), IResource.FILE); 729 if (status.getSeverity() == IStatus.ERROR) 730 return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); 732 return new RefactoringStatus(); 733 } 734 735 private String createNewPath(String newName) { 736 return fType.getCompilationUnit().getResource().getFullPath().removeLastSegments(1).append(newName).toString(); 737 } 738 739 private RefactoringStatus checkTypesImportedInCu() throws CoreException { 740 IImportDeclaration imp= getImportedType(fType.getCompilationUnit(), getNewElementName()); 741 742 if (imp == null) 743 return null; 744 745 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_imported, 746 new Object []{getNewElementName(), fType.getCompilationUnit().getResource().getFullPath()}); 747 IJavaElement grandParent= imp.getParent().getParent(); 748 if (grandParent instanceof ICompilationUnit) 749 return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(imp)); 750 751 return null; 752 } 753 754 private RefactoringStatus checkTypesInPackage() throws CoreException { 755 IType type= Checks.findTypeInPackage(fType.getPackageFragment(), getNewElementName()); 756 if (type == null || ! type.exists()) 757 return null; 758 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_exists, 759 new String []{getNewElementName(), fType.getPackageFragment().getElementName()}); 760 return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(type)); 761 } 762 763 private RefactoringStatus checkEnclosedTypes() throws CoreException { 764 IType enclosedType= findEnclosedType(fType, getNewElementName()); 765 if (enclosedType == null) 766 return null; 767 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_encloses, 768 new String []{JavaModelUtil.getFullyQualifiedName(fType), getNewElementName()}); 769 return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosedType)); 770 } 771 772 private RefactoringStatus checkEnclosingTypes() { 773 IType enclosingType= findEnclosingType(fType, getNewElementName()); 774 if (enclosingType == null) 775 return null; 776 777 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed, 778 new String []{JavaModelUtil.getFullyQualifiedName(fType), getNewElementName()}); 779 return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosingType)); 780 } 781 782 private static IType findEnclosedType(IType type, String newName) throws CoreException { 783 IType[] enclosedTypes= type.getTypes(); 784 for (int i= 0; i < enclosedTypes.length; i++){ 785 if (newName.equals(enclosedTypes[i].getElementName()) || findEnclosedType(enclosedTypes[i], newName) != null) 786 return enclosedTypes[i]; 787 } 788 return null; 789 } 790 791 private static IType findEnclosingType(IType type, String newName) { 792 IType enclosing= type.getDeclaringType(); 793 while (enclosing != null){ 794 if (newName.equals(enclosing.getElementName())) 795 return enclosing; 796 else 797 enclosing= enclosing.getDeclaringType(); 798 } 799 return null; 800 } 801 802 private static IImportDeclaration getImportedType(ICompilationUnit cu, String typeName) throws CoreException { 803 IImportDeclaration[] imports= cu.getImports(); 804 String dotTypeName= "." + typeName; for (int i= 0; i < imports.length; i++){ 806 if (imports[i].getElementName().endsWith(dotTypeName)) 807 return imports[i]; 808 } 809 return null; 810 } 811 812 private RefactoringStatus checkForMethodsWithConstructorNames() throws CoreException{ 813 IMethod[] methods= fType.getMethods(); 814 for (int i= 0; i < methods.length; i++){ 815 if (methods[i].isConstructor()) 816 continue; 817 RefactoringStatus check= Checks.checkIfConstructorName(methods[i], methods[i].getElementName(), getNewElementName()); 818 if (check != null) 819 return check; 820 } 821 return null; 822 } 823 824 private RefactoringStatus checkImportedTypes() throws CoreException { 825 RefactoringStatus result= new RefactoringStatus(); 826 IImportDeclaration[] imports= fType.getCompilationUnit().getImports(); 827 for (int i= 0; i < imports.length; i++) 828 analyzeImportDeclaration(imports[i], result); 829 return result; 830 } 831 832 private RefactoringStatus checkTypesInCompilationUnit() { 833 RefactoringStatus result= new RefactoringStatus(); 834 if (! Checks.isTopLevel(fType)){ IType siblingType= fType.getDeclaringType().getType(getNewElementName()); 836 if (siblingType.exists()){ 837 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type_exists, 838 new String []{getNewElementName(), JavaModelUtil.getFullyQualifiedName(fType.getDeclaringType())}); 839 result.addError(msg, JavaStatusContext.create(siblingType)); 840 } 841 } 842 return result; 843 } 844 845 private RefactoringStatus analyseEnclosedTypes() throws CoreException { 846 final ISourceRange typeRange= fType.getSourceRange(); 847 final RefactoringStatus result= new RefactoringStatus(); 848 CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false); 849 cuNode.accept(new ASTVisitor(){ 850 851 public boolean visit(TypeDeclaration node){ if (node.getStartPosition() <= typeRange.getOffset()) 853 return true; 854 if (node.getStartPosition() > typeRange.getOffset() + typeRange.getLength()) 855 return true; 856 857 if (getNewElementName().equals(node.getName().getIdentifier())){ 858 RefactoringStatusContext context= JavaStatusContext.create(fType.getCompilationUnit(), node); 859 String msg= null; 860 if (node.isLocalTypeDeclaration()){ 861 msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_local_type, 862 new String []{JavaElementUtil.createSignature(fType), getNewElementName()}); 863 } 864 else if (node.isMemberTypeDeclaration()){ 865 msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type, 866 new String []{JavaElementUtil.createSignature(fType), getNewElementName()}); 867 } 868 if (msg != null) 869 result.addError(msg, context); 870 } 871 872 MethodDeclaration[] methods= node.getMethods(); 873 for (int i= 0; i < methods.length; i++) { 874 if (Modifier.isNative(methods[i].getModifiers())){ 875 RefactoringStatusContext context= JavaStatusContext.create(fType.getCompilationUnit(), methods[i]); 876 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed_type_native, node.getName().getIdentifier()); 877 result.addWarning(msg, context); 878 } 879 } 880 return true; 881 } 882 }); 883 return result; 884 } 885 886 private static ICompilationUnit getCompilationUnit(IImportDeclaration imp) { 887 return (ICompilationUnit)imp.getParent().getParent(); 888 } 889 890 private void analyzeImportedTypes(IType[] types, RefactoringStatus result, IImportDeclaration imp) throws CoreException { 891 for (int i= 0; i < types.length; i++) { 892 if (JdtFlags.isPublic(types[i]) && types[i].getElementName().equals(getNewElementName())){ 894 String msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_name_conflict1, 895 new Object []{JavaModelUtil.getFullyQualifiedName(types[i]), getFullPath(getCompilationUnit(imp))}); 896 result.addError(msg, JavaStatusContext.create(imp)); 897 } 898 } 899 } 900 901 private static IJavaElement convertFromImportDeclaration(IImportDeclaration declaration) throws CoreException { 902 if (declaration.isOnDemand()){ 903 String packageName= declaration.getElementName().substring(0, declaration.getElementName().length() - 2); 904 return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), packageName); 905 } else 906 return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), declaration.getElementName()); 907 } 908 909 private void analyzeImportDeclaration(IImportDeclaration imp, RefactoringStatus result) throws CoreException{ 910 if (!imp.isOnDemand()) 911 return; 913 IJavaElement imported= convertFromImportDeclaration(imp); 914 if (imported == null) 915 return; 916 917 if (imported instanceof IPackageFragment){ 918 ICompilationUnit[] cus= ((IPackageFragment)imported).getCompilationUnits(); 919 for (int i= 0; i < cus.length; i++) { 920 analyzeImportedTypes(cus[i].getTypes(), result, imp); 921 } 922 } else { 923 analyzeImportedTypes(((IType)imported).getTypes(), result, imp); 925 } 926 } 927 928 931 private RefactoringStatus analyzeAffectedCompilationUnits(IProgressMonitor pm) throws CoreException { 932 RefactoringStatus result= new RefactoringStatus(); 933 934 result.merge(Checks.checkCompileErrorsInAffectedFiles(fReferences, fType.getResource())); 935 936 pm.beginTask("", fReferences.length); result.merge(checkConflictingTypes(pm)); 938 return result; 939 } 940 941 private RefactoringStatus checkConflictingTypes(IProgressMonitor pm) throws CoreException { 942 RefactoringStatus result= new RefactoringStatus(); 943 IJavaSearchScope scope= RefactoringScopeFactory.create(fType); 944 SearchPattern pattern= SearchPattern.createPattern(getNewElementName(), 945 IJavaSearchConstants.TYPE, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); 946 ICompilationUnit[] cusWithReferencesToConflictingTypes= RefactoringSearchEngine.findAffectedCompilationUnits(pattern, scope, pm, result); 947 if (cusWithReferencesToConflictingTypes.length == 0) 948 return result; 949 ICompilationUnit[] cusWithReferencesToRenamedType= getCus(fReferences); 950 951 ICompilationUnit[] intersection= isIntersectionEmpty(cusWithReferencesToRenamedType, cusWithReferencesToConflictingTypes); 952 if (intersection.length == 0) 953 return result; 954 955 for (int i= 0; i < intersection.length; i++) { 956 RefactoringStatusContext context= JavaStatusContext.create(intersection[i]); 957 String message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_another_type, 958 new String []{getNewElementName(), intersection[i].getElementName()}); 959 result.addError(message, context); 960 } 961 return result; 962 } 963 964 private static ICompilationUnit[] isIntersectionEmpty(ICompilationUnit[] a1, ICompilationUnit[] a2){ 965 Set set1= new HashSet (Arrays.asList(a1)); 966 Set set2= new HashSet (Arrays.asList(a2)); 967 set1.retainAll(set2); 968 return (ICompilationUnit[]) set1.toArray(new ICompilationUnit[set1.size()]); 969 } 970 971 private static ICompilationUnit[] getCus(SearchResultGroup[] searchResultGroups){ 972 List cus= new ArrayList (searchResultGroups.length); 973 for (int i= 0; i < searchResultGroups.length; i++) { 974 ICompilationUnit cu= searchResultGroups[i].getCompilationUnit(); 975 if (cu != null) 976 cus.add(cu); 977 } 978 return (ICompilationUnit[]) cus.toArray(new ICompilationUnit[cus.size()]); 979 } 980 981 private static String getFullPath(ICompilationUnit cu) { 982 Assert.isTrue(cu.exists()); 983 return cu.getResource().getFullPath().toString(); 984 } 985 986 public Change createChange(IProgressMonitor monitor) throws CoreException { 987 try { 988 monitor.beginTask(RefactoringCoreMessages.RenameTypeRefactoring_creating_change, 4); 989 String project= null; 990 IJavaProject javaProject= fType.getJavaProject(); 991 if (javaProject != null) 992 project= javaProject.getElementName(); 993 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE; 994 try { 995 if (!Flags.isPrivate(fType.getFlags())) 996 flags|= RefactoringDescriptor.MULTI_CHANGE; 997 if (fType.isAnonymous() || fType.isLocal()) 998 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 999 } catch (JavaModelException exception) { 1000 JavaPlugin.log(exception); 1001 } 1002 final String description= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description_short, fType.getElementName()); 1003 final String header= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description, new String [] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()}); 1004 final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString(); 1005 final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE); 1006 descriptor.setProject(project); 1007 descriptor.setDescription(description); 1008 descriptor.setComment(comment); 1009 descriptor.setFlags(flags); 1010 descriptor.setJavaElement(fType); 1011 descriptor.setNewName(getNewElementName()); 1012 descriptor.setUpdateQualifiedNames(fUpdateQualifiedNames); 1013 descriptor.setUpdateTextualOccurrences(fUpdateTextualMatches); 1014 descriptor.setUpdateReferences(fUpdateReferences); 1015 if (fUpdateQualifiedNames && fFilePatterns != null && !"".equals(fFilePatterns)) descriptor.setFileNamePatterns(fFilePatterns); 1017 descriptor.setUpdateSimilarDeclarations(fUpdateSimilarElements); 1018 descriptor.setMatchStrategy(fRenamingStrategy); 1019 final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameTypeProcessor_change_name); 1020 1021 if (fChangeManager.containsChangesIn(fType.getCompilationUnit())) { 1022 TextChange textChange= fChangeManager.get(fType.getCompilationUnit()); 1023 if (textChange instanceof TextFileChange) { 1024 ((TextFileChange) textChange).setSaveMode(TextFileChange.FORCE_SAVE); 1025 } 1026 } 1027 result.addAll(fChangeManager.getAllChanges()); 1028 if (willRenameCU()) { 1029 IResource resource= fType.getCompilationUnit().getResource(); 1030 if (resource != null && resource.isLinked()) { 1031 String ext= resource.getFileExtension(); 1032 String renamedResourceName; 1033 if (ext == null) 1034 renamedResourceName= getNewElementName(); 1035 else 1036 renamedResourceName= getNewElementName() + '.' + ext; 1037 result.add(new RenameResourceChange(null, fType.getCompilationUnit().getResource(), renamedResourceName, comment)); 1038 } else { 1039 String renamedCUName= JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), getNewElementName()); 1040 result.add(new RenameCompilationUnitChange(fType.getCompilationUnit(), renamedCUName)); 1041 } 1042 } 1043 monitor.worked(1); 1044 return result; 1045 } finally { 1046 fChangeManager= null; 1047 } 1048 } 1049 1050 public Change postCreateChange(Change[] participantChanges, IProgressMonitor pm) throws CoreException { 1051 if (fQualifiedNameSearchResult != null) { 1052 try { 1053 return fQualifiedNameSearchResult.getSingleChange(Changes.getModifiedFiles(participantChanges)); 1054 } finally { 1055 fQualifiedNameSearchResult= null; 1056 } 1057 } else { 1058 return null; 1059 } 1060 } 1061 1062 private boolean willRenameCU() throws CoreException{ 1063 String name = JavaCore.removeJavaLikeExtension(fType.getCompilationUnit().getElementName()); 1064 if (! (Checks.isTopLevel(fType) && name.equals(fType.getElementName()))) 1065 return false; 1066 if (! checkNewPathValidity().isOK()) 1067 return false; 1068 if (! Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName()).isOK()) 1069 return false; 1070 return true; 1071 } 1072 1073 private void createChanges(IProgressMonitor pm) throws CoreException { 1074 try{ 1075 pm.beginTask("", 12); pm.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_creating_changes); 1077 1078 if (fUpdateReferences) 1079 addReferenceUpdates(fChangeManager, new SubProgressMonitor(pm, 3)); 1080 1081 1083 pm.worked(1); 1084 1085 IResource resource= fType.getCompilationUnit().getResource(); 1086 if ((resource != null && resource.isLinked()) || !willRenameCU()) { 1089 addTypeDeclarationUpdate(fChangeManager); 1090 pm.worked(1); 1091 1092 addConstructorRenames(fChangeManager); 1093 pm.worked(1); 1094 } else { 1095 pm.worked(2); 1096 } 1097 1098 if (fUpdateTextualMatches) { 1099 pm.subTask(RefactoringCoreMessages.RenameTypeRefactoring_searching_text); 1100 TextMatchUpdater.perform(new SubProgressMonitor(pm, 1), RefactoringScopeFactory.create(fType), this, fChangeManager, fReferences); 1101 if (fUpdateSimilarElements) 1102 addSimilarElementsTextualUpdates(fChangeManager, new SubProgressMonitor(pm, 3)); 1103 } 1104 1105 } finally{ 1106 pm.done(); 1107 } 1108 } 1109 1110 private void addTypeDeclarationUpdate(TextChangeManager manager) throws CoreException { 1111 String name= RefactoringCoreMessages.RenameTypeRefactoring_update; 1112 int typeNameLength= fType.getElementName().length(); 1113 ICompilationUnit cu= fType.getCompilationUnit(); 1114 TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(fType.getNameRange().getOffset(), typeNameLength, getNewElementName())); 1115 } 1116 1117 private void addConstructorRenames(TextChangeManager manager) throws CoreException { 1118 ICompilationUnit cu= fType.getCompilationUnit(); 1119 IMethod[] methods= fType.getMethods(); 1120 int typeNameLength= fType.getElementName().length(); 1121 for (int i= 0; i < methods.length; i++){ 1122 if (methods[i].isConstructor()) { 1123 1129 String name= RefactoringCoreMessages.RenameTypeRefactoring_rename_constructor; 1130 TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(methods[i].getNameRange().getOffset(), typeNameLength, getNewElementName())); 1131 } 1132 } 1133 } 1134 1135 private void addReferenceUpdates(TextChangeManager manager, IProgressMonitor pm) { 1136 pm.beginTask("", fReferences.length); for (int i= 0; i < fReferences.length; i++){ 1138 ICompilationUnit cu= fReferences[i].getCompilationUnit(); 1139 if (cu == null) 1140 continue; 1141 1142 String name= RefactoringCoreMessages.RenameTypeRefactoring_update_reference; 1143 SearchMatch[] results= fReferences[i].getSearchResults(); 1144 1145 for (int j= 0; j < results.length; j++){ 1146 SearchMatch match= results[j]; 1147 ReplaceEdit replaceEdit= new ReplaceEdit(match.getOffset(), match.getLength(), getNewElementName()); 1148 TextChangeCompatibility.addTextEdit(manager.get(cu), name, replaceEdit, CATEGORY_TYPE_RENAME); 1149 } 1150 pm.worked(1); 1151 } 1152 } 1153 1154 private void computeQualifiedNameMatches(IProgressMonitor pm) throws CoreException { 1155 IPackageFragment fragment= fType.getPackageFragment(); 1156 if (fQualifiedNameSearchResult == null) 1157 fQualifiedNameSearchResult= new QualifiedNameSearchResult(); 1158 QualifiedNameFinder.process(fQualifiedNameSearchResult, fType.getFullyQualifiedName(), 1159 fragment.getElementName() + "." + getNewElementName(), fFilePatterns, fType.getJavaProject().getProject(), pm); 1161 } 1162 1163 public RefactoringStatus initialize(RefactoringArguments arguments) { 1164 if (arguments instanceof JavaRefactoringArguments) { 1165 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 1166 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 1167 if (handle != null) { 1168 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1169 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 1170 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE); 1171 else 1172 fType= (IType) element; 1173 } else 1174 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 1175 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 1176 if (name != null && !"".equals(name)) setNewElementName(name); 1178 else 1179 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 1180 final String patterns= extended.getAttribute(ATTRIBUTE_PATTERNS); 1181 if (patterns != null && !"".equals(patterns)) fFilePatterns= patterns; 1183 final String references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES); 1184 if (references != null) { 1185 fUpdateReferences= Boolean.valueOf(references).booleanValue(); 1186 } else 1187 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES)); 1188 final String matches= extended.getAttribute(ATTRIBUTE_TEXTUAL_MATCHES); 1189 if (matches != null) { 1190 fUpdateTextualMatches= Boolean.valueOf(matches).booleanValue(); 1191 } else 1192 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TEXTUAL_MATCHES)); 1193 final String qualified= extended.getAttribute(ATTRIBUTE_QUALIFIED); 1194 if (qualified != null) { 1195 fUpdateQualifiedNames= Boolean.valueOf(qualified).booleanValue(); 1196 } else 1197 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_QUALIFIED)); 1198 final String similarDeclarations= extended.getAttribute(ATTRIBUTE_SIMILAR_DECLARATIONS); 1199 if (similarDeclarations != null) 1200 fUpdateSimilarElements= Boolean.valueOf(similarDeclarations).booleanValue(); 1201 else 1202 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_SIMILAR_DECLARATIONS)); 1203 final String similarDeclarationsMatchingStrategy= extended.getAttribute(ATTRIBUTE_MATCHING_STRATEGY); 1204 if (similarDeclarationsMatchingStrategy != null) { 1205 try { 1206 fRenamingStrategy= Integer.valueOf(similarDeclarationsMatchingStrategy).intValue(); 1207 } catch (NumberFormatException e) { 1208 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new String [] {similarDeclarationsMatchingStrategy, ATTRIBUTE_QUALIFIED})); 1209 } 1210 } else 1211 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MATCHING_STRATEGY)); 1212 } else 1213 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 1214 return new RefactoringStatus(); 1215 } 1216 1217 1219 1226 private RefactoringStatus initializeSimilarElementsRenameProcessors(IProgressMonitor progressMonitor, CheckConditionsContext context) throws CoreException { 1227 1228 Assert.isNotNull(fPreloadedElementToName); 1229 Assert.isNotNull(fPreloadedElementToSelection); 1230 1231 final RefactoringStatus status= new RefactoringStatus(); 1232 final Set handledTopLevelMethods= new HashSet (); 1233 final Set warnings= new HashSet (); 1234 final List processors= new ArrayList (); 1235 fFinalSimilarElementToName= new HashMap (); 1236 1237 CompilationUnit currentResolvedCU= null; 1238 ICompilationUnit currentCU= null; 1239 1240 int current= 0; 1241 final int max= fPreloadedElementToName.size(); 1242 1243 progressMonitor.beginTask("", max * 3); progressMonitor.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_checking_similarly_named_declarations_refactoring_conditions); 1245 1246 for (Iterator iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) { 1247 1248 final IJavaElement element= (IJavaElement) iter.next(); 1249 1250 current++; 1251 progressMonitor.worked(3); 1252 1253 if (! ((Boolean ) (fPreloadedElementToSelection.get(element))).booleanValue()) 1255 continue; 1256 1257 if (fFinalSimilarElementToName.containsKey(element)) 1259 continue; 1260 1261 ICompilationUnit newCU= (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT); 1263 1264 if (!newCU.equals(currentCU)) { 1265 1266 checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors); 1267 1268 if (status.hasFatalError()) 1269 return status; 1270 1271 currentResolvedCU= null; 1273 currentCU= newCU; 1274 processors.clear(); 1275 } 1276 1277 final String newName= (String ) fPreloadedElementToName.get(element); 1278 RefactoringProcessor processor= null; 1279 1280 if (element instanceof ILocalVariable) { 1281 final ILocalVariable currentLocal= (ILocalVariable) element; 1282 1283 if (currentResolvedCU == null) 1284 currentResolvedCU= new RefactoringASTParser(AST.JLS3).parse(currentCU, true); 1285 1286 processor= createLocalRenameProcessor(currentLocal, newName, currentResolvedCU); 1287 1288 1290 if (status.hasFatalError()) 1291 return status; 1292 fFinalSimilarElementToName.put(currentLocal, newName); 1293 } 1294 if (element instanceof IField) { 1295 final IField currentField= (IField) element; 1296 processor= createFieldRenameProcessor(currentField, newName); 1297 1298 status.merge(checkForConflictingRename(currentField, newName)); 1299 if (status.hasFatalError()) 1300 return status; 1301 fFinalSimilarElementToName.put(currentField, newName); 1302 } 1303 if (element instanceof IMethod) { 1304 IMethod currentMethod= (IMethod) element; 1305 if (MethodChecks.isVirtual(currentMethod)) { 1306 1307 final IType declaringType= currentMethod.getDeclaringType(); 1308 ITypeHierarchy hierarchy= null; 1309 if (!declaringType.isInterface()) 1310 hierarchy= declaringType.newTypeHierarchy(new NullProgressMonitor()); 1311 1312 final IMethod topmost= MethodChecks.getTopmostMethod(currentMethod, hierarchy, new NullProgressMonitor()); 1313 if (topmost != null) 1314 currentMethod= topmost; 1315 if (handledTopLevelMethods.contains(currentMethod)) 1316 continue; 1317 handledTopLevelMethods.add(currentMethod); 1318 final IMethod[] ripples= MethodChecks.getOverriddenMethods(currentMethod, new NullProgressMonitor()); 1319 1320 if (checkForWarnings(warnings, newName, ripples)) 1321 continue; 1322 1323 status.merge(checkForConflictingRename(ripples, newName)); 1324 if (status.hasFatalError()) 1325 return status; 1326 1327 processor= createVirtualMethodRenameProcessor(currentMethod, newName, ripples, hierarchy); 1328 fFinalSimilarElementToName.put(currentMethod, newName); 1329 for (int i= 0; i < ripples.length; i++) { 1330 fFinalSimilarElementToName.put(ripples[i], newName); 1331 } 1332 } else { 1333 1334 status.merge(checkForConflictingRename(new IMethod[] { currentMethod }, newName)); 1335 if (status.hasFatalError()) 1336 break; 1337 1338 fFinalSimilarElementToName.put(currentMethod, newName); 1339 1340 processor= createNonVirtualMethodRenameProcessor(currentMethod, newName); 1341 } 1342 } 1343 1344 progressMonitor.subTask(Messages.format(RefactoringCoreMessages.RenameTypeProcessor_progress_current_total, new Object [] { String.valueOf(current), String.valueOf(max)})); 1345 1346 status.merge(processor.checkInitialConditions(new NoOverrideProgressMonitor(progressMonitor, 1))); 1347 1348 if (status.hasFatalError()) 1349 return status; 1350 1351 status.merge(processor.checkFinalConditions(new NoOverrideProgressMonitor(progressMonitor, 1), context)); 1352 1353 if (status.hasFatalError()) 1354 return status; 1355 1356 processors.add(processor); 1357 1358 progressMonitor.worked(1); 1359 1360 if (progressMonitor.isCanceled()) 1361 throw new OperationCanceledException(); 1362 } 1363 1364 checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors); 1366 1367 status.merge(addWarnings(warnings)); 1368 1369 progressMonitor.done(); 1370 return status; 1371 } 1372 1373 private void checkCUCompleteConditions(final RefactoringStatus status, CompilationUnit currentResolvedCU, ICompilationUnit currentCU, List processors) throws CoreException { 1374 1375 List locals= getProcessorsOfType(processors, RenameLocalVariableProcessor.class); 1377 if (!locals.isEmpty()) { 1378 RenameAnalyzeUtil.LocalAnalyzePackage[] analyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[locals.size()]; 1379 TextChangeManager manager= new TextChangeManager(); 1380 int current= 0; 1381 TextChange textChange= manager.get(currentCU); 1382 textChange.setKeepPreviewEdits(true); 1383 for (Iterator iterator= locals.iterator(); iterator.hasNext();) { 1384 RenameLocalVariableProcessor localProcessor= (RenameLocalVariableProcessor) iterator.next(); 1385 RenameAnalyzeUtil.LocalAnalyzePackage analyzePackage= localProcessor.getLocalAnalyzePackage(); 1386 analyzePackages[current]= analyzePackage; 1387 for (int i= 0; i < analyzePackage.fOccurenceEdits.length; i++) { 1388 TextChangeCompatibility.addTextEdit(textChange, "", analyzePackage.fOccurenceEdits[i], GroupCategorySet.NONE); } 1390 current++; 1391 } 1392 status.merge(RenameAnalyzeUtil.analyzeLocalRenames(analyzePackages, textChange, currentResolvedCU, false)); 1393 } 1394 1395 1401 } 1402 1403 private List getProcessorsOfType(List processors, Class type) { 1404 List tmp= new ArrayList (); 1405 for (Iterator iter= processors.iterator(); iter.hasNext();) { 1406 RefactoringProcessor element= (RefactoringProcessor) iter.next(); 1407 if (element.getClass().equals(type)) 1408 tmp.add(element); 1409 } 1410 return tmp; 1411 } 1412 1413 1415 1425 private RefactoringStatus checkForConflictingRename(IMethod[] methods, String newName) { 1426 RefactoringStatus status= new RefactoringStatus(); 1427 for (Iterator iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) { 1428 IJavaElement element= (IJavaElement) iter.next(); 1429 if (element instanceof IMethod) { 1430 IMethod alreadyRegisteredMethod= (IMethod) element; 1431 String alreadyRegisteredMethodName= (String ) fFinalSimilarElementToName.get(element); 1432 for (int i= 0; i < methods.length; i++) { 1433 IMethod method2= methods[i]; 1434 if ( (alreadyRegisteredMethodName.equals(newName)) && (method2.getDeclaringType().equals(alreadyRegisteredMethod.getDeclaringType())) 1435 && (sameParams(alreadyRegisteredMethod, method2))) { 1436 String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_methods_same_new_name, new String [] { alreadyRegisteredMethod.getElementName(), 1437 method2.getElementName(), alreadyRegisteredMethod.getDeclaringType().getFullyQualifiedName(), newName }); 1438 status.addFatalError(message); 1439 return status; 1440 } 1441 } 1442 } 1443 } 1444 return status; 1445 } 1446 1447 private static boolean sameParams(IMethod method, IMethod method2) { 1448 1449 if (method.getNumberOfParameters() != method2.getNumberOfParameters()) 1450 return false; 1451 1452 String [] params= method.getParameterTypes(); 1453 String [] params2= method2.getParameterTypes(); 1454 1455 for (int i= 0; i < params.length; i++) { 1456 String t1= Signature.getSimpleName(Signature.toString(params[i])); 1457 String t2= Signature.getSimpleName(Signature.toString(params2[i])); 1458 if (!t1.equals(t2)) { 1459 return false; 1460 } 1461 } 1462 return true; 1463 } 1464 1465 1478 private RefactoringStatus checkForConflictingRename(IField currentField, String newName) { 1479 RefactoringStatus status= new RefactoringStatus(); 1480 for (Iterator iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) { 1481 IJavaElement element= (IJavaElement) iter.next(); 1482 if (element instanceof IField) { 1483 IField alreadyRegisteredField= (IField) element; 1484 String alreadyRegisteredFieldName= (String ) fFinalSimilarElementToName.get(element); 1485 if (alreadyRegisteredFieldName.equals(newName)) { 1486 if (alreadyRegisteredField.getDeclaringType().equals(currentField.getDeclaringType())) { 1487 1488 String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_fields_same_new_name, new String [] { alreadyRegisteredField.getElementName(), 1489 currentField.getElementName(), alreadyRegisteredField.getDeclaringType().getFullyQualifiedName(), newName }); 1490 status.addFatalError(message); 1491 return status; 1492 } 1493 } 1494 } 1495 } 1496 return status; 1497 } 1498 1499 private RefactoringStatus addWarnings(final Set warnings) { 1500 RefactoringStatus status= new RefactoringStatus(); 1501 1502 for (Iterator iter= warnings.iterator(); iter.hasNext();) { 1504 final Warning warning= (Warning) iter.next(); 1505 final IMethod[] elements= warning.getRipple(); 1506 if (warning.isSelectionWarning()) { 1507 String message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_deselected_method_is_overridden, 1508 new String [] { JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT), 1509 JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) }); 1510 status.addWarning(message); 1511 } 1512 if (warning.isNameWarning()) { 1513 String message= Messages.format( 1514 RefactoringCoreMessages.RenameTypeProcessor_renamed_method_is_overridden, new String [] { 1515 JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT), 1516 JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) }); 1517 status.addWarning(message); 1518 } 1519 for (int i= 0; i < elements.length; i++) 1520 fPreloadedElementToSelection.put(elements[i], Boolean.FALSE); 1521 } 1522 return status; 1523 } 1524 1525 1529 private boolean checkForWarnings(final Set warnings, final String newName, final IMethod[] ripples) { 1530 1531 boolean addSelectionWarning= false; 1532 boolean addNameWarning= false; 1533 for (int i= 0; i < ripples.length; i++) { 1534 String newNameOfRipple= (String ) fPreloadedElementToName.get(ripples[i]); 1535 Boolean selected= (Boolean ) fPreloadedElementToSelection.get(ripples[i]); 1536 1537 if (selected == null) 1541 continue; 1542 1543 if (!selected.booleanValue()) 1544 addSelectionWarning= true; 1545 1546 if (!newName.equals(newNameOfRipple)) 1547 addNameWarning= true; 1548 } 1549 if (addSelectionWarning || addNameWarning) 1550 warnings.add(new Warning(ripples, addSelectionWarning, addNameWarning)); 1551 1552 return (addSelectionWarning || addNameWarning); 1553 } 1554 1555 private class Warning { 1556 1557 private IMethod[] fRipple; 1558 private boolean fSelectionWarning; 1559 private boolean fNameWarning; 1560 1561 public Warning(IMethod[] ripple, boolean isSelectionWarning, boolean isNameWarning) { 1562 fRipple= ripple; 1563 fSelectionWarning= isSelectionWarning; 1564 fNameWarning= isNameWarning; 1565 } 1566 1567 public boolean isNameWarning() { 1568 return fNameWarning; 1569 } 1570 1571 public IMethod[] getRipple() { 1572 return fRipple; 1573 } 1574 1575 public boolean isSelectionWarning() { 1576 return fSelectionWarning; 1577 } 1578 } 1579 1580 1582 private RenameMethodProcessor createVirtualMethodRenameProcessor(IMethod currentMethod, String newMethodName, IMethod[] ripples, ITypeHierarchy hierarchy) throws JavaModelException { 1583 RenameMethodProcessor processor= new RenameVirtualMethodProcessor(currentMethod, ripples, fChangeManager, hierarchy, CATEGORY_METHOD_RENAME); 1584 initMethodProcessor(processor, newMethodName); 1585 return processor; 1586 } 1587 1588 private RenameMethodProcessor createNonVirtualMethodRenameProcessor(IMethod currentMethod, String newMethodName) { 1589 RenameMethodProcessor processor= new RenameNonVirtualMethodProcessor(currentMethod, fChangeManager, CATEGORY_METHOD_RENAME); 1590 initMethodProcessor(processor, newMethodName); 1591 return processor; 1592 } 1593 1594 private void initMethodProcessor(RenameMethodProcessor processor, String newMethodName) { 1595 processor.setNewElementName(newMethodName); 1596 processor.setUpdateReferences(getUpdateReferences()); 1597 } 1598 1599 private RenameFieldProcessor createFieldRenameProcessor(final IField field, final String newName) { 1600 final RenameFieldProcessor processor= new RenameFieldProcessor(field, fChangeManager, CATEGORY_FIELD_RENAME); 1601 processor.setNewElementName(newName); 1602 processor.setRenameGetter(false); 1603 processor.setRenameSetter(false); 1604 processor.setUpdateReferences(getUpdateReferences()); 1605 processor.setUpdateTextualMatches(false); 1606 return processor; 1607 } 1608 1609 private RenameLocalVariableProcessor createLocalRenameProcessor(final ILocalVariable local, final String newName, final CompilationUnit compilationUnit) { 1610 final RenameLocalVariableProcessor processor= new RenameLocalVariableProcessor(local, fChangeManager, compilationUnit, CATEGORY_LOCAL_RENAME); 1611 processor.setNewElementName(newName); 1612 processor.setUpdateReferences(getUpdateReferences()); 1613 return processor; 1614 } 1615 1616 1618 1619 1630 private void addSimilarElementsTextualUpdates(TextChangeManager manager, IProgressMonitor monitor) throws CoreException { 1631 1632 final Map simpleNames= new HashMap (); 1633 final List forbiddenSimpleNames= new ArrayList (); 1634 1635 for (Iterator iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) { 1636 final IJavaElement element= (IJavaElement) iter.next(); 1637 if (element instanceof IField) { 1638 1639 if (forbiddenSimpleNames.contains(element.getElementName())) 1640 continue; 1641 1642 final String registeredNewName= (String ) simpleNames.get(element.getElementName()); 1643 final String newNameToCheck= (String ) fFinalSimilarElementToName.get(element); 1644 if (registeredNewName == null) 1645 simpleNames.put(element.getElementName(), newNameToCheck); 1646 else if (!registeredNewName.equals(newNameToCheck)) 1647 forbiddenSimpleNames.add(element.getElementName()); 1648 } 1649 } 1650 1651 for (Iterator iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) { 1652 final IJavaElement element= (IJavaElement) iter.next(); 1653 if (element instanceof IField) { 1654 final IField field= (IField) element; 1655 final String newName= (String ) fFinalSimilarElementToName.get(field); 1656 TextMatchUpdater.perform(monitor, RefactoringScopeFactory.create(field), field.getElementName(), field.getDeclaringType().getFullyQualifiedName(), newName, manager, 1657 new SearchResultGroup[0], forbiddenSimpleNames.contains(field.getElementName())); 1658 } 1659 } 1660 } 1661 1662 1664 1669 public Map getSimilarElementsToNewNames() { 1670 return fPreloadedElementToName; 1671 } 1672 1673 1678 public Map getSimilarElementsToSelection() { 1679 return fPreloadedElementToSelection; 1680 } 1681 1682 1688 public void resetSelectedSimilarElements() { 1689 Assert.isNotNull(fPreloadedElementToName); 1690 for (Iterator iter= fPreloadedElementToNameDefault.keySet().iterator(); iter.hasNext();) { 1691 final IJavaElement element= (IJavaElement) iter.next(); 1692 fPreloadedElementToName.put(element, fPreloadedElementToNameDefault.get(element)); 1693 fPreloadedElementToSelection.put(element, Boolean.TRUE); 1694 } 1695 } 1696 1697 1701 public boolean hasSimilarElementsToRename() { 1702 if (!fUpdateSimilarElements) 1703 return false; 1704 if (fPreloadedElementToName == null) 1705 return false; 1706 if (fPreloadedElementToName.size() == 0) 1707 return false; 1708 return true; 1709 } 1710} 1711 | Popular Tags |