1 11 package org.eclipse.jdt.internal.corext.refactoring.code; 12 13 import java.lang.reflect.Modifier ; 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 21 import org.eclipse.core.runtime.Assert; 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 import org.eclipse.core.runtime.NullProgressMonitor; 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.RefactoringDescriptor; 32 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 33 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 34 35 import org.eclipse.jdt.core.Flags; 36 import org.eclipse.jdt.core.IClassFile; 37 import org.eclipse.jdt.core.ICompilationUnit; 38 import org.eclipse.jdt.core.IJavaElement; 39 import org.eclipse.jdt.core.IJavaProject; 40 import org.eclipse.jdt.core.IMember; 41 import org.eclipse.jdt.core.IMethod; 42 import org.eclipse.jdt.core.IPackageFragment; 43 import org.eclipse.jdt.core.IType; 44 import org.eclipse.jdt.core.ITypeHierarchy; 45 import org.eclipse.jdt.core.JavaModelException; 46 import org.eclipse.jdt.core.dom.AST; 47 import org.eclipse.jdt.core.dom.ASTNode; 48 import org.eclipse.jdt.core.dom.ASTParser; 49 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 50 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 51 import org.eclipse.jdt.core.dom.Block; 52 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; 53 import org.eclipse.jdt.core.dom.CompilationUnit; 54 import org.eclipse.jdt.core.dom.Expression; 55 import org.eclipse.jdt.core.dom.ExpressionStatement; 56 import org.eclipse.jdt.core.dom.IBinding; 57 import org.eclipse.jdt.core.dom.IMethodBinding; 58 import org.eclipse.jdt.core.dom.ITypeBinding; 59 import org.eclipse.jdt.core.dom.Javadoc; 60 import org.eclipse.jdt.core.dom.MethodDeclaration; 61 import org.eclipse.jdt.core.dom.MethodInvocation; 62 import org.eclipse.jdt.core.dom.Name; 63 import org.eclipse.jdt.core.dom.ParameterizedType; 64 import org.eclipse.jdt.core.dom.PrimitiveType; 65 import org.eclipse.jdt.core.dom.ReturnStatement; 66 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 67 import org.eclipse.jdt.core.dom.Statement; 68 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 69 import org.eclipse.jdt.core.dom.ThisExpression; 70 import org.eclipse.jdt.core.dom.Type; 71 import org.eclipse.jdt.core.dom.TypeParameter; 72 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; 73 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 74 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 75 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 76 import org.eclipse.jdt.core.search.IJavaSearchConstants; 77 import org.eclipse.jdt.core.search.IJavaSearchScope; 78 import org.eclipse.jdt.core.search.SearchMatch; 79 import org.eclipse.jdt.core.search.SearchPattern; 80 81 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 82 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 83 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 84 import org.eclipse.jdt.internal.corext.dom.Bindings; 85 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 86 import org.eclipse.jdt.internal.corext.refactoring.Checks; 87 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 88 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 89 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 90 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 91 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 92 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 93 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 94 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 95 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 96 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 97 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 98 import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2; 99 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; 100 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; 101 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor; 102 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 103 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 104 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 105 import org.eclipse.jdt.internal.corext.util.JdtFlags; 106 import org.eclipse.jdt.internal.corext.util.Messages; 107 import org.eclipse.jdt.internal.corext.util.MethodOverrideTester; 108 109 import org.eclipse.jdt.ui.CodeGeneration; 110 import org.eclipse.jdt.ui.JavaElementLabels; 111 112 import org.eclipse.jdt.internal.ui.JavaPlugin; 113 114 137 public class IntroduceIndirectionRefactoring extends ScriptableRefactoring { 138 139 142 private ICompilationUnit fSelectionCompilationUnit; 143 146 private IClassFile fSelectionClassFile; 147 151 private int fSelectionStart; 152 156 private int fSelectionLength; 157 161 private MethodInvocation fSelectionMethodInvocation; 162 163 165 168 private IType fIntermediaryClass; 169 172 private ITypeBinding fIntermediaryClassBinding; 173 176 private String fIntermediaryMethodName; 177 181 private ITypeBinding fIntermediaryFirstParameterType; 182 183 185 188 private IMethod fTargetMethod; 189 192 private IMethodBinding fTargetMethodBinding; 193 194 196 200 private boolean fUpdateReferences; 201 204 private Map fRewrites; 205 209 private TextChangeManager fTextChangeManager; 210 211 213 216 private MemberVisibilityAdjustor fAdjustor; 217 220 private Map fIntermediaryAdjustments; 221 222 223 private class NoOverrideProgressMonitor extends SubProgressMonitor { 224 225 public NoOverrideProgressMonitor(IProgressMonitor monitor, int ticks) { 226 super(monitor, ticks, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); 227 } 228 229 public void setTaskName(String name) { 230 } 232 } 233 234 236 public IntroduceIndirectionRefactoring(ICompilationUnit unit, int offset, int length) { 237 fSelectionCompilationUnit= unit; 238 initialize(offset, length); 239 } 240 241 public IntroduceIndirectionRefactoring(IClassFile file, int offset, int length) { 242 fSelectionClassFile= file; 243 initialize(offset, length); 244 } 245 246 public IntroduceIndirectionRefactoring(IMethod method) { 247 fTargetMethod= method; 248 initialize(0, 0); 249 } 250 251 private void initialize(int offset, int length) { 252 fSelectionStart= offset; 253 fSelectionLength= length; 254 fUpdateReferences= true; 255 } 256 257 259 public String getName() { 260 return RefactoringCoreMessages.IntroduceIndirectionRefactoring_introduce_indirection_name; 261 } 262 263 public IJavaProject getProject() { 264 if (fSelectionCompilationUnit != null) 265 return fSelectionCompilationUnit.getJavaProject(); 266 if (fSelectionClassFile != null) 267 return fSelectionClassFile.getJavaProject(); 268 if (fTargetMethod != null) 269 return fTargetMethod.getJavaProject(); 270 return null; 271 } 272 273 public IPackageFragment getInvocationPackage() { 274 return fSelectionCompilationUnit != null ? (IPackageFragment) fSelectionCompilationUnit.getAncestor(IJavaElement.PACKAGE_FRAGMENT) : null; 275 } 276 277 public boolean canEnableUpdateReferences() { 278 return true; 279 } 280 281 public void setEnableUpdateReferences(boolean updateReferences) { 282 fUpdateReferences= updateReferences; 283 } 284 285 public RefactoringStatus setIntermediaryMethodName(String newMethodName) { 286 Assert.isNotNull(newMethodName); 287 fIntermediaryMethodName= newMethodName; 288 RefactoringStatus stat= Checks.checkMethodName(newMethodName); 289 stat.merge(checkOverloading()); 290 return stat; 291 } 292 293 private RefactoringStatus checkOverloading() { 294 try { 295 if (fIntermediaryClass != null) { 296 IMethod[] toCheck= fIntermediaryClass.getMethods(); 297 for (int i= 0; i < toCheck.length; i++) { 298 IMethod method= toCheck[i]; 299 if (method.getElementName().equals(fIntermediaryMethodName)) 300 return RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_duplicate_method_name_in_declaring_class_error, 301 fIntermediaryMethodName)); 302 } 303 } 304 } catch (JavaModelException e) { 305 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_could_not_parse_declaring_class_error); 306 } 307 return new RefactoringStatus(); 308 } 309 310 public String getIntermediaryMethodName() { 311 return fIntermediaryMethodName; 312 } 313 314 318 public RefactoringStatus setIntermediaryClassName(String fullyQualifiedTypeName) { 319 IType target= null; 320 321 try { 322 if (fullyQualifiedTypeName.length() == 0) 323 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_class_not_selected_error); 324 325 target= getProject().findType(fullyQualifiedTypeName, new NullProgressMonitor()); 327 if (target == null || !target.exists()) 328 return RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_class_does_not_exist_error, fullyQualifiedTypeName)); 329 if (target.isAnnotation()) 330 return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_annotation); 331 if (target.isInterface()) 332 return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_on_interface); 333 } catch (JavaModelException e) { 334 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_unable_determine_declaring_type); 335 } 336 337 if (target.isReadOnly()) 338 return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_readonly); 339 340 if (target.isBinary()) 341 return RefactoringStatus.createErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_binary); 342 343 fIntermediaryClass= target; 344 345 return new RefactoringStatus(); 346 } 347 348 352 public String getIntermediaryClassName() { 353 return fIntermediaryClass != null ? JavaModelUtil.getFullyQualifiedName(fIntermediaryClass) : ""; } 355 356 358 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { 359 try { 360 pm.beginTask(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_activation, 1); 361 fRewrites= new HashMap (); 362 363 367 if (fTargetMethod == null) { 368 370 if (fSelectionStart == 0) 371 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this_selection); 372 373 CompilationUnit selectionCURoot; 375 ASTNode selectionNode; 376 if (fSelectionCompilationUnit != null) { 377 selectionCURoot= getCachedCURewrite(fSelectionCompilationUnit).getRoot(); 379 selectionNode= getSelectedNode(fSelectionCompilationUnit, selectionCURoot, fSelectionStart, fSelectionLength); 380 } else { 381 ASTParser parser= ASTParser.newParser(AST.JLS3); 383 parser.setResolveBindings(true); 384 parser.setSource(fSelectionClassFile); 385 selectionCURoot= (CompilationUnit) parser.createAST(null); 386 selectionNode= getSelectedNode(null, selectionCURoot, fSelectionStart, fSelectionLength); 387 } 388 389 if (selectionNode == null) 390 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this_selection); 391 392 IMethodBinding targetMethodBinding= null; 393 394 if (selectionNode.getNodeType() == ASTNode.METHOD_INVOCATION) { 395 targetMethodBinding= ((MethodInvocation) selectionNode).resolveMethodBinding(); 396 } else if (selectionNode.getNodeType() == ASTNode.METHOD_DECLARATION) { 397 targetMethodBinding= ((MethodDeclaration) selectionNode).resolveBinding(); 398 } else if (selectionNode.getNodeType() == ASTNode.SUPER_METHOD_INVOCATION) { 399 targetMethodBinding= ((SuperMethodInvocation) selectionNode).resolveMethodBinding(); 402 } else { 403 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this_selection); 404 } 405 fTargetMethodBinding= targetMethodBinding.getMethodDeclaration(); fTargetMethod= (IMethod) fTargetMethodBinding.getJavaElement(); 407 408 if (selectionNode instanceof MethodInvocation && fSelectionCompilationUnit != null) 410 fSelectionMethodInvocation= (MethodInvocation) selectionNode; 411 412 } else { 413 415 if (fTargetMethod.getDeclaringType().isAnnotation()) 416 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_annotation); 417 418 if (fTargetMethod.getCompilationUnit() != null) { 419 CompilationUnit selectionCURoot= getCachedCURewrite(fTargetMethod.getCompilationUnit()).getRoot(); 421 MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fTargetMethod, selectionCURoot); 422 fTargetMethodBinding= declaration.resolveBinding().getMethodDeclaration(); 423 } else { 424 ASTParser parser= ASTParser.newParser(AST.JLS3); 426 parser.setProject(fTargetMethod.getJavaProject()); 427 IBinding[] bindings= parser.createBindings(new IJavaElement[] { fTargetMethod }, null); 428 fTargetMethodBinding= ((IMethodBinding) bindings[0]).getMethodDeclaration(); 429 } 430 } 431 432 if (fTargetMethod == null || fTargetMethodBinding == null || (!RefactoringAvailabilityTester.isIntroduceIndirectionAvailable(fTargetMethod))) 433 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_on_this_selection); 434 435 if (fTargetMethod.getDeclaringType().isLocal() || fTargetMethod.getDeclaringType().isAnonymous()) 436 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_for_local_or_anonymous_types); 437 438 if (fTargetMethod.isConstructor()) 439 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_not_available_for_constructors); 440 441 if (fIntermediaryMethodName == null) 442 fIntermediaryMethodName= fTargetMethod.getElementName(); 443 444 if (fIntermediaryClass == null) { 445 if (fSelectionCompilationUnit != null && !fSelectionCompilationUnit.isReadOnly()) 446 fIntermediaryClass= getEnclosingInitialSelectionMember().getDeclaringType(); 447 else if (!fTargetMethod.isBinary() && !fTargetMethod.isReadOnly()) 448 fIntermediaryClass= fTargetMethod.getDeclaringType(); 449 } 450 451 return new RefactoringStatus(); 452 } finally { 453 pm.done(); 454 } 455 } 456 457 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { 458 459 RefactoringStatus result= new RefactoringStatus(); 460 fTextChangeManager= new TextChangeManager(); 461 fIntermediaryFirstParameterType= null; 462 fIntermediaryClassBinding= null; 463 for (Iterator iter= fRewrites.values().iterator(); iter.hasNext();) 464 ((CompilationUnitRewrite) iter.next()).clearASTAndImportRewrites(); 465 466 int startupTicks= 5; 467 int hierarchyTicks= 5; 468 int visibilityTicks= 5; 469 int referenceTicks= fUpdateReferences ? 30 : 5; 470 int creationTicks= 5; 471 472 pm.beginTask("", startupTicks + hierarchyTicks + visibilityTicks + referenceTicks + creationTicks); pm.setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions); 474 475 result.merge(Checks.checkMethodName(fIntermediaryMethodName)); 476 if (result.hasFatalError()) 477 return result; 478 479 if (fIntermediaryClass == null) 480 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_run_without_intermediary_type); 481 482 CompilationUnitRewrite imRewrite= getCachedCURewrite(fIntermediaryClass.getCompilationUnit()); 484 fIntermediaryClassBinding= typeToBinding(fIntermediaryClass, imRewrite.getRoot()); 485 486 fAdjustor= new MemberVisibilityAdjustor(fIntermediaryClass, fIntermediaryClass); 487 fIntermediaryAdjustments= new HashMap (); 488 489 if (fIntermediaryClassBinding.isNested() && !Modifier.isStatic(fIntermediaryClassBinding.getModifiers())) 491 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_create_in_nested_nonstatic, JavaStatusContext.create(fIntermediaryClass)); 492 493 pm.worked(startupTicks); 494 if (pm.isCanceled()) 495 throw new OperationCanceledException(); 496 497 if (fUpdateReferences) { 498 pm.setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions + " " + RefactoringCoreMessages.IntroduceIndirectionRefactoring_looking_for_references); result.merge(updateReferences(new NoOverrideProgressMonitor(pm, referenceTicks))); 500 pm.setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions); 501 } else { 502 if (fSelectionMethodInvocation != null) { 504 fIntermediaryFirstParameterType= getExpressionType(fSelectionMethodInvocation); 505 final IMember enclosing= getEnclosingInitialSelectionMember(); 506 result.merge(updateMethodInvocation(fSelectionMethodInvocation, enclosing, getCachedCURewrite(fSelectionCompilationUnit))); 508 509 if (!isRewriteKept(fSelectionCompilationUnit)) 510 createChangeAndDiscardRewrite(fSelectionCompilationUnit); 511 512 result.merge(adjustVisibility(fIntermediaryClass, enclosing.getDeclaringType(), new NoOverrideProgressMonitor(pm, 0))); 515 } 516 pm.worked(referenceTicks); 517 } 518 519 if (pm.isCanceled()) 520 throw new OperationCanceledException(); 521 522 if (fIntermediaryFirstParameterType == null) 523 fIntermediaryFirstParameterType= fTargetMethodBinding.getDeclaringClass(); 524 525 527 IType actualTargetType= (IType) fIntermediaryFirstParameterType.getJavaElement(); 528 if (!fTargetMethod.getDeclaringType().equals(actualTargetType)) { 529 IMethod actualTargetMethod= new MethodOverrideTester(actualTargetType, actualTargetType.newSupertypeHierarchy(null)).findOverriddenMethodInHierarchy(actualTargetType, fTargetMethod); 530 fTargetMethod= actualTargetMethod; 531 fTargetMethodBinding= findMethodBindingInHierarchy(fIntermediaryFirstParameterType, actualTargetMethod); 532 Assert.isNotNull(fTargetMethodBinding); 533 } 534 535 result.merge(checkCanCreateIntermediaryMethod()); 536 createIntermediaryMethod(); 537 pm.worked(creationTicks); 538 539 pm.setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions + " " + RefactoringCoreMessages.IntroduceIndirectionRefactoring_adjusting_visibility); result.merge(updateTargetVisibility(new NoOverrideProgressMonitor(pm, 0))); 541 result.merge(updateIntermediaryVisibility(new NoOverrideProgressMonitor(pm, 0))); 542 pm.worked(visibilityTicks); 543 pm.setTaskName(RefactoringCoreMessages.IntroduceIndirectionRefactoring_checking_conditions); 544 545 createChangeAndDiscardRewrite(fIntermediaryClass.getCompilationUnit()); 546 547 result.merge(Checks.validateModifiesFiles(getAllFilesToModify(), getValidationContext())); 548 pm.done(); 549 550 return result; 551 } 552 553 private RefactoringStatus updateTargetVisibility(IProgressMonitor monitor) throws JavaModelException, CoreException { 554 555 RefactoringStatus result= new RefactoringStatus(); 556 557 561 564 result.merge(adjustVisibility((IType) fIntermediaryFirstParameterType.getJavaElement(), fIntermediaryClass, monitor)); 565 if (result.hasError()) 566 return result; 568 ModifierKeyword neededVisibility= getNeededVisibility(fTargetMethod, fIntermediaryClass); 569 if (neededVisibility != null) { 570 571 result.merge(adjustVisibility(fTargetMethod, neededVisibility, monitor)); 572 if (result.hasError()) 573 return result; 575 ITypeHierarchy hierarchy= fTargetMethod.getDeclaringType().newTypeHierarchy(null); 577 MethodOverrideTester tester= new MethodOverrideTester(fTargetMethod.getDeclaringType(), hierarchy); 578 IType[] subtypes= hierarchy.getAllSubtypes(fTargetMethod.getDeclaringType()); 579 for (int i= 0; i < subtypes.length; i++) { 580 IMethod method= tester.findOverridingMethodInType(subtypes[i], fTargetMethod); 581 if (method != null && method.exists()) { 582 result.merge(adjustVisibility(method, neededVisibility, monitor)); 583 if (monitor.isCanceled()) 584 throw new OperationCanceledException(); 585 586 if (result.hasError()) 587 return result; } 589 } 590 } 591 592 return result; 593 } 594 595 private RefactoringStatus updateIntermediaryVisibility(NoOverrideProgressMonitor monitor) throws JavaModelException { 596 return rewriteVisibility(fIntermediaryAdjustments, fRewrites, monitor); 597 } 598 599 private RefactoringStatus updateReferences(IProgressMonitor monitor) throws CoreException { 600 601 RefactoringStatus result= new RefactoringStatus(); 602 603 monitor.beginTask("", 90); 605 if (monitor.isCanceled()) 606 throw new OperationCanceledException(); 607 608 IMethod[] ripple= RippleMethodFinder2.getRelatedMethods(fTargetMethod, false, new NoOverrideProgressMonitor(monitor, 10), null); 609 610 if (monitor.isCanceled()) 611 throw new OperationCanceledException(); 612 613 SearchResultGroup[] references= Checks.excludeCompilationUnits(getReferences(ripple, new NoOverrideProgressMonitor(monitor, 10), result), result); 614 615 if (result.hasFatalError()) 616 return result; 617 618 result.merge(Checks.checkCompileErrorsInAffectedFiles(references)); 619 620 if (monitor.isCanceled()) 621 throw new OperationCanceledException(); 622 623 int ticksPerCU= references.length == 0 ? 0 : 70 / references.length; 624 625 for (int i= 0; i < references.length; i++) { 626 SearchResultGroup group= references[i]; 627 SearchMatch[] searchResults= group.getSearchResults(); 628 CompilationUnitRewrite currentCURewrite= getCachedCURewrite(group.getCompilationUnit()); 629 630 for (int j= 0; j < searchResults.length; j++) { 631 632 SearchMatch match= searchResults[j]; 633 if (match.isInsideDocComment()) 634 continue; 635 636 IMember enclosingMember= (IMember) match.getElement(); 637 ASTNode target= getSelectedNode(group.getCompilationUnit(), currentCURewrite.getRoot(), match.getOffset(), match.getLength()); 638 639 if (target instanceof SuperMethodInvocation) { 640 result.merge(createWarningAboutCall(enclosingMember, target, RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_super_keyword)); 642 continue; 643 } 644 645 Assert.isTrue(target instanceof MethodInvocation, "Element of call should be a MethodInvocation."); 647 MethodInvocation invocation= (MethodInvocation) target; 648 ITypeBinding typeBinding= getExpressionType(invocation); 649 650 if (fIntermediaryFirstParameterType == null) { 651 fIntermediaryFirstParameterType= typeBinding.getTypeDeclaration(); 653 } else { 654 result.merge(findCommonParent(typeBinding.getTypeDeclaration())); 656 } 657 658 if (result.hasFatalError()) 659 return result; 660 661 result.merge(updateMethodInvocation(invocation, enclosingMember, currentCURewrite)); 663 664 result.merge(adjustVisibility(fIntermediaryClass, enclosingMember.getDeclaringType(), new NoOverrideProgressMonitor(monitor, 0))); 667 668 if (monitor.isCanceled()) 669 throw new OperationCanceledException(); 670 } 671 672 if (!isRewriteKept(group.getCompilationUnit())) 673 createChangeAndDiscardRewrite(group.getCompilationUnit()); 674 675 monitor.worked(ticksPerCU); 676 } 677 678 monitor.done(); 679 return result; 680 } 681 682 private RefactoringStatus findCommonParent(ITypeBinding typeBinding) throws JavaModelException { 683 684 RefactoringStatus status= new RefactoringStatus(); 685 686 ITypeBinding highest= fIntermediaryFirstParameterType; 687 ITypeBinding current= typeBinding; 688 689 if (current.equals(highest) || Bindings.isSuperType(highest, current)) 690 return status; 692 693 ITypeBinding[] currentAndSupers= getTypeAndAllSuperTypes(current); 696 ITypeBinding[] highestAndSupers= getTypeAndAllSuperTypes(highest); 697 698 ITypeBinding foundBinding= null; 699 for (int i1= 0; i1 < currentAndSupers.length; i1++) { 700 for (int i2= 0; i2 < highestAndSupers.length; i2++) { 701 if (highestAndSupers[i2].isEqualTo(currentAndSupers[i1]) 702 && (Bindings.findMethodInHierarchy(highestAndSupers[i2], fTargetMethodBinding.getName(), fTargetMethodBinding.getParameterTypes()) != null)) { 703 foundBinding= highestAndSupers[i2]; 704 break; 705 } 706 } 707 if (foundBinding != null) 708 break; 709 } 710 711 if (foundBinding != null) { 712 fIntermediaryFirstParameterType= foundBinding; 713 } else { 714 String type1= fIntermediaryFirstParameterType.getQualifiedName(); 715 String type2= current.getQualifiedName(); 716 status.addFatalError(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_open_hierarchy_error, new String [] { type1, type2 })); 717 } 718 719 return status; 720 } 721 722 724 public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { 725 final Map arguments= new HashMap (); 726 String project= null; 727 IJavaProject javaProject= fTargetMethod.getJavaProject(); 728 if (javaProject != null) 729 project= javaProject.getElementName(); 730 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; 731 final IType declaring= fTargetMethod.getDeclaringType(); 732 try { 733 if (declaring.isLocal() || declaring.isAnonymous()) 734 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 735 } catch (JavaModelException exception) { 736 JavaPlugin.log(exception); 737 } 738 final String description= Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_descriptor_description_short, fTargetMethod.getElementName()); 739 final String header= Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_descriptor_description, new String [] { JavaElementLabels.getTextLabel(fTargetMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(declaring, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 740 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 741 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_original_pattern, JavaElementLabels.getTextLabel(fTargetMethod, JavaElementLabels.ALL_FULLY_QUALIFIED))); 742 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_method_pattern, fIntermediaryMethodName)); 743 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_declaring_pattern, JavaElementLabels.getTextLabel(fIntermediaryClass, JavaElementLabels.ALL_FULLY_QUALIFIED))); 744 if (fUpdateReferences) 745 comment.addSetting(RefactoringCoreMessages.JavaRefactoringDescriptor_update_references); 746 final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.INTRODUCE_INDIRECTION, project, description, comment.asString(), arguments, flags); 747 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fTargetMethod)); 748 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fIntermediaryMethodName); 749 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1, descriptor.elementToHandle(fIntermediaryClass)); 750 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES, Boolean.valueOf(fUpdateReferences).toString()); 751 return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.IntroduceIndirectionRefactoring_introduce_indirection, fTextChangeManager.getAllChanges()); 752 } 753 754 756 762 private RefactoringStatus checkCanCreateIntermediaryMethod() throws JavaModelException { 763 List parameterBindings= new ArrayList (); 765 if (!isStaticTarget()) 766 parameterBindings.add(fIntermediaryFirstParameterType); 767 parameterBindings.addAll(Arrays.asList(fTargetMethodBinding.getParameterTypes())); 768 return Checks.checkMethodInType(fIntermediaryClassBinding, fIntermediaryMethodName, (ITypeBinding[]) parameterBindings.toArray(new ITypeBinding[parameterBindings.size()])); 769 } 770 771 private void createIntermediaryMethod() throws CoreException { 772 773 CompilationUnitRewrite imRewrite= getCachedCURewrite(fIntermediaryClass.getCompilationUnit()); 774 AST ast= imRewrite.getAST(); 775 MethodDeclaration intermediary= ast.newMethodDeclaration(); 776 777 intermediary.setName(ast.newSimpleName(fIntermediaryMethodName)); 779 780 List modifiers= intermediary.modifiers(); 782 modifiers.add(imRewrite.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD)); 783 modifiers.add(imRewrite.getAST().newModifier(ModifierKeyword.STATIC_KEYWORD)); 784 785 String targetParameterName= StubUtility.suggestArgumentName(getProject(), fIntermediaryFirstParameterType.getName(), fTargetMethod.getParameterNames()); 787 788 if (!isStaticTarget()) { 789 SingleVariableDeclaration parameter= imRewrite.getAST().newSingleVariableDeclaration(); 791 Type t= imRewrite.getImportRewrite().addImport(fIntermediaryFirstParameterType, imRewrite.getAST()); 792 if (fIntermediaryFirstParameterType.isGenericType()) { 793 ParameterizedType parameterized= imRewrite.getAST().newParameterizedType(t); 794 ITypeBinding[] typeParameters= fIntermediaryFirstParameterType.getTypeParameters(); 795 for (int i= 0; i < typeParameters.length; i++) 796 parameterized.typeArguments().add(imRewrite.getImportRewrite().addImport(typeParameters[i], imRewrite.getAST())); 797 t= parameterized; 798 } 799 parameter.setType(t); 800 parameter.setName(imRewrite.getAST().newSimpleName(targetParameterName)); 801 intermediary.parameters().add(parameter); 802 } 803 copyArguments(intermediary, imRewrite); 805 806 if (!isStaticTarget() && fIntermediaryFirstParameterType.isGenericType()) 808 addTypeParameters(imRewrite, intermediary.typeParameters(), fIntermediaryFirstParameterType); 809 810 copyTypeParameters(intermediary, imRewrite); 812 813 intermediary.setReturnType2(imRewrite.getImportRewrite().addImport(fTargetMethodBinding.getReturnType(), ast)); 815 816 copyExceptions(intermediary, imRewrite); 818 819 MethodInvocation invocation= imRewrite.getAST().newMethodInvocation(); 821 invocation.setName(imRewrite.getAST().newSimpleName(fTargetMethod.getElementName())); 822 if (isStaticTarget()) { 823 Type type= imRewrite.getImportRewrite().addImport(fTargetMethodBinding.getDeclaringClass(), ast); 824 invocation.setExpression(ASTNodeFactory.newName(ast, ASTNodes.asString(type))); 825 } else { 826 invocation.setExpression(imRewrite.getAST().newSimpleName(targetParameterName)); 827 } 828 copyInvocationParameters(invocation, ast); 829 Statement call= encapsulateInvocation(intermediary, invocation); 830 831 final Block body= imRewrite.getAST().newBlock(); 832 body.statements().add(call); 833 intermediary.setBody(body); 834 835 ICompilationUnit targetCU= imRewrite.getCu(); 837 if (StubUtility.doAddComments(targetCU.getJavaProject())) { 838 String comment= CodeGeneration.getMethodComment(targetCU, getIntermediaryClassName(), intermediary, null, StubUtility.getLineDelimiterUsed(targetCU)); 839 if (comment != null) { 840 Javadoc javadoc= (Javadoc) imRewrite.getASTRewrite().createStringPlaceholder(comment, ASTNode.JAVADOC); 841 intermediary.setJavadoc(javadoc); 842 } 843 } 844 845 847 AbstractTypeDeclaration type= (AbstractTypeDeclaration) typeToDeclaration(fIntermediaryClass, imRewrite.getRoot()); 849 ChildListPropertyDescriptor typeBodyDeclarationsProperty= typeToBodyDeclarationProperty(fIntermediaryClass, imRewrite.getRoot()); 850 851 ListRewrite bodyDeclarationsListRewrite= imRewrite.getASTRewrite().getListRewrite(type, typeBodyDeclarationsProperty); 852 bodyDeclarationsListRewrite.insertAt(intermediary, ASTNodes.getInsertionIndex(intermediary, type.bodyDeclarations()), imRewrite 853 .createGroupDescription(RefactoringCoreMessages.IntroduceIndirectionRefactoring_group_description_create_new_method)); 854 } 855 856 private void addTypeParameters(CompilationUnitRewrite imRewrite, List newTypeParameters, ITypeBinding parent) { 857 858 ITypeBinding enclosing= parent.getDeclaringClass(); 859 if (enclosing != null) 860 addTypeParameters(imRewrite, newTypeParameters, enclosing); 861 862 ITypeBinding[] typeParameters= parent.getTypeParameters(); 863 for (int i= 0; i < typeParameters.length; i++) { 864 TypeParameter ntp= imRewrite.getAST().newTypeParameter(); 865 ntp.setName(imRewrite.getAST().newSimpleName(typeParameters[i].getName())); 866 ITypeBinding[] bounds= typeParameters[i].getTypeBounds(); 867 for (int j= 0; j < bounds.length; j++) 868 if (!"java.lang.Object".equals(bounds[j].getQualifiedName())) ntp.typeBounds().add(imRewrite.getImportRewrite().addImport(bounds[j], imRewrite.getAST())); 870 newTypeParameters.add(ntp); 871 } 872 } 873 874 private Statement encapsulateInvocation(MethodDeclaration declaration, MethodInvocation invocation) { 875 final Type type= declaration.getReturnType2(); 876 877 if (type == null || (type instanceof PrimitiveType && PrimitiveType.VOID.equals( ((PrimitiveType) type).getPrimitiveTypeCode()))) 878 return invocation.getAST().newExpressionStatement(invocation); 879 880 ReturnStatement statement= invocation.getAST().newReturnStatement(); 881 statement.setExpression(invocation); 882 return statement; 883 } 884 885 private void copyInvocationParameters(MethodInvocation invocation, AST ast) throws JavaModelException { 886 String [] names= fTargetMethod.getParameterNames(); 887 for (int i= 0; i < names.length; i++) 888 invocation.arguments().add(ast.newSimpleName(names[i])); 889 } 890 891 private void copyArguments(MethodDeclaration intermediary, CompilationUnitRewrite rew) throws JavaModelException { 892 String [] names= fTargetMethod.getParameterNames(); 893 ITypeBinding[] types= fTargetMethodBinding.getParameterTypes(); 894 for (int i= 0; i < names.length; i++) { 895 ITypeBinding typeBinding= types[i]; 896 SingleVariableDeclaration newElement= rew.getAST().newSingleVariableDeclaration(); 897 newElement.setName(rew.getAST().newSimpleName(names[i])); 898 899 if (i == (names.length - 1) && fTargetMethodBinding.isVarargs()) { 900 newElement.setVarargs(true); 901 if (typeBinding.isArray()) 902 typeBinding= typeBinding.getComponentType(); 903 } 904 905 newElement.setType(rew.getImportRewrite().addImport(typeBinding, rew.getAST())); 906 intermediary.parameters().add(newElement); 907 } 908 } 909 910 private void copyTypeParameters(MethodDeclaration intermediary, CompilationUnitRewrite rew) { 911 ITypeBinding[] typeParameters= fTargetMethodBinding.getTypeParameters(); 912 for (int i= 0; i < typeParameters.length; i++) { 913 ITypeBinding current= typeParameters[i]; 914 915 TypeParameter parameter= rew.getAST().newTypeParameter(); 916 parameter.setName(rew.getAST().newSimpleName(current.getName())); 917 ITypeBinding[] bounds= current.getTypeBounds(); 918 for (int j= 0; j < bounds.length; j++) 919 if (!"java.lang.Object".equals(bounds[j].getQualifiedName())) parameter.typeBounds().add(rew.getImportRewrite().addImport(bounds[j], rew.getAST())); 921 922 intermediary.typeParameters().add(parameter); 923 } 924 } 925 926 private void copyExceptions(MethodDeclaration intermediary, CompilationUnitRewrite imRewrite) { 927 ITypeBinding[] exceptionTypes= fTargetMethodBinding.getExceptionTypes(); 928 for (int i= 0; i < exceptionTypes.length; i++) { 929 final String qualifiedName= imRewrite.getImportRewrite().addImport(exceptionTypes[i]); 930 intermediary.thrownExceptions().add(ASTNodeFactory.newName(imRewrite.getAST(), qualifiedName)); 931 } 932 } 933 934 936 private RefactoringStatus updateMethodInvocation(MethodInvocation originalInvocation, IMember enclosing, CompilationUnitRewrite unitRewriter) throws JavaModelException { 937 938 RefactoringStatus status= new RefactoringStatus(); 939 940 if (originalInvocation.typeArguments().size() > 0) 943 return createWarningAboutCall(enclosing, originalInvocation, RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_type_arguments); 944 945 MethodInvocation newInvocation= unitRewriter.getAST().newMethodInvocation(); 946 List newInvocationArgs= newInvocation.arguments(); 947 List originalInvocationArgs= originalInvocation.arguments(); 948 949 String qualifier= unitRewriter.getImportRewrite().addImport(fIntermediaryClassBinding); 951 newInvocation.setExpression(ASTNodeFactory.newName(unitRewriter.getAST(), qualifier)); 952 newInvocation.setName(unitRewriter.getAST().newSimpleName(getIntermediaryMethodName())); 953 954 final Expression expression= originalInvocation.getExpression(); 955 956 if (!isStaticTarget()) { 957 if (expression == null) { 959 ThisExpression expr= unitRewriter.getAST().newThisExpression(); 961 RefactoringStatus qualifierStatus= qualifyThisExpression(expr, originalInvocation, enclosing, unitRewriter); 962 status.merge(qualifierStatus); 963 if (qualifierStatus.hasEntries()) 964 return status; 966 newInvocationArgs.add(expr); 967 } else { 968 ASTNode expressionAsParam= unitRewriter.getASTRewrite().createMoveTarget(expression); 969 newInvocationArgs.add(expressionAsParam); 970 } 971 } else { 972 if (expression != null) { 973 if (! (expression instanceof Name) || ASTNodes.getTypeBinding((Name) expression) == null) 976 return createWarningAboutCall(enclosing, originalInvocation, RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_static_expression_access); 977 } 978 } 979 980 for (int i= 0; i < originalInvocationArgs.size(); i++) { 981 Expression originalInvocationArg= (Expression) originalInvocationArgs.get(i); 982 ASTNode movedArg= unitRewriter.getASTRewrite().createMoveTarget(originalInvocationArg); 983 newInvocationArgs.add(movedArg); 984 } 985 986 unitRewriter.getASTRewrite().replace(originalInvocation, newInvocation, 987 unitRewriter.createGroupDescription(RefactoringCoreMessages.IntroduceIndirectionRefactoring_group_description_replace_call)); 988 989 return status; 990 } 991 992 1013 private RefactoringStatus qualifyThisExpression(ThisExpression expr, MethodInvocation originalInvocation, IMember enclosing, CompilationUnitRewrite unitRewriter) { 1014 1015 RefactoringStatus status= new RefactoringStatus(); 1016 1017 IMethodBinding methodBinding= originalInvocation.resolveMethodBinding(); 1018 MethodDeclaration methodDeclaration= (MethodDeclaration) ASTNodes.findDeclaration(methodBinding, originalInvocation.getRoot()); 1019 1020 ITypeBinding currentTypeBinding= null; 1021 if (methodDeclaration != null) { 1022 if (ASTNodes.isParent(originalInvocation, methodDeclaration.getParent())) 1024 currentTypeBinding= methodBinding.getDeclaringClass(); 1025 else 1026 currentTypeBinding= ASTNodes.getEnclosingType(originalInvocation); 1027 } else { 1028 ASTNode currentTypeDeclaration= getEnclosingTypeDeclaration(originalInvocation); 1030 currentTypeBinding= ASTNodes.getEnclosingType(currentTypeDeclaration); 1031 while (currentTypeDeclaration != null && (Bindings.findMethodInHierarchy(currentTypeBinding, methodBinding.getName(), methodBinding.getParameterTypes()) == null)) { 1032 currentTypeDeclaration= getEnclosingTypeDeclaration(currentTypeDeclaration.getParent()); 1033 currentTypeBinding= ASTNodes.getEnclosingType(currentTypeDeclaration); 1034 } 1035 } 1036 1037 if (currentTypeBinding == null) { 1038 status.merge(createWarningAboutCall(enclosing, originalInvocation, RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_declaring_type_not_found)); 1039 return status; 1040 } 1041 1042 ITypeBinding typeOfCall= ASTNodes.getEnclosingType(originalInvocation); 1043 if (!typeOfCall.equals(currentTypeBinding)) { 1044 if (currentTypeBinding.isAnonymous()) { 1045 status.merge(createWarningAboutCall(enclosing, originalInvocation, RefactoringCoreMessages.IntroduceIndirectionRefactoring_call_warning_anonymous_cannot_qualify)); 1047 } else { 1048 expr.setQualifier(unitRewriter.getAST().newSimpleName(currentTypeBinding.getName())); 1049 } 1050 } else { 1051 } 1053 1054 return status; 1055 } 1056 1057 1059 1062 private IMethodBinding findMethodBindingInHierarchy(ITypeBinding currentTypeBinding, IMethod methodDeclaration) { 1063 IMethodBinding[] bindings= currentTypeBinding.getDeclaredMethods(); 1064 for (int i= 0; i < bindings.length; i++) 1065 if (methodDeclaration.equals(bindings[i].getJavaElement())) 1066 return bindings[i]; 1067 1068 ITypeBinding superClass= currentTypeBinding.getSuperclass(); 1069 if (superClass != null) { 1070 IMethodBinding b= findMethodBindingInHierarchy(superClass, methodDeclaration); 1071 if (b != null) 1072 return b; 1073 } 1074 ITypeBinding[] interfaces= currentTypeBinding.getInterfaces(); 1075 for (int i= 0; i < interfaces.length; i++) { 1076 IMethodBinding b= findMethodBindingInHierarchy(interfaces[i], methodDeclaration); 1077 if (b != null) 1078 return b; 1079 } 1080 return null; 1081 } 1082 1083 1086 private ITypeBinding[] getTypeAndAllSuperTypes(ITypeBinding type) { 1087 List result= new ArrayList (); 1088 collectSuperTypes(type, result); 1089 return (ITypeBinding[]) result.toArray(new ITypeBinding[result.size()]); 1090 } 1091 1092 private void collectSuperTypes(ITypeBinding curr, List list) { 1093 if (list.add(curr.getTypeDeclaration())) { 1094 ITypeBinding[] interfaces= curr.getInterfaces(); 1095 for (int i= 0; i < interfaces.length; i++) { 1096 collectSuperTypes(interfaces[i], list); 1097 } 1098 ITypeBinding superClass= curr.getSuperclass(); 1099 if (superClass != null) { 1100 collectSuperTypes(superClass, list); 1101 } 1102 } 1103 } 1104 1105 private CompilationUnitRewrite getCachedCURewrite(ICompilationUnit unit) { 1106 CompilationUnitRewrite rewrite= (CompilationUnitRewrite) fRewrites.get(unit); 1107 if (rewrite == null) { 1108 rewrite= new CompilationUnitRewrite(unit); 1109 fRewrites.put(unit, rewrite); 1110 } 1111 return rewrite; 1112 } 1113 1114 private boolean isRewriteKept(ICompilationUnit compilationUnit) { 1115 return fIntermediaryClass.getCompilationUnit().equals(compilationUnit); 1116 } 1117 1118 private void createChangeAndDiscardRewrite(ICompilationUnit compilationUnit) throws CoreException { 1119 CompilationUnitRewrite rewrite= (CompilationUnitRewrite) fRewrites.get(compilationUnit); 1120 if (rewrite != null) { 1121 fTextChangeManager.manage(compilationUnit, rewrite.createChange()); 1122 fRewrites.remove(compilationUnit); 1123 } 1124 } 1125 1126 private SearchResultGroup[] getReferences(IMethod[] methods, IProgressMonitor pm, RefactoringStatus status) throws CoreException { 1127 SearchPattern pattern= RefactoringSearchEngine.createOrPattern(methods, IJavaSearchConstants.REFERENCES); 1128 IJavaSearchScope scope= RefactoringScopeFactory.create(fIntermediaryClass, false); 1129 return RefactoringSearchEngine.search(pattern, scope, pm, status); 1130 } 1131 1132 private ITypeBinding typeToBinding(IType type, CompilationUnit root) throws JavaModelException { 1133 ASTNode typeNode= typeToDeclaration(type, root); 1134 if (type.isAnonymous()) { 1135 return ((AnonymousClassDeclaration) typeNode).resolveBinding(); 1136 } else { 1137 return ((AbstractTypeDeclaration) typeNode).resolveBinding(); 1138 } 1139 } 1140 1141 private ASTNode typeToDeclaration(IType type, CompilationUnit root) throws JavaModelException { 1142 Name intermediateName= (Name) NodeFinder.perform(root, type.getNameRange()); 1143 if (type.isAnonymous()) { 1144 return ASTNodes.getParent(intermediateName, AnonymousClassDeclaration.class); 1145 } else { 1146 return ASTNodes.getParent(intermediateName, AbstractTypeDeclaration.class); 1147 } 1148 } 1149 1150 private ASTNode getEnclosingTypeDeclaration(ASTNode node) { 1151 while (node != null) { 1152 if (node instanceof AbstractTypeDeclaration) { 1153 return node; 1154 } else if (node instanceof AnonymousClassDeclaration) { 1155 return node; 1156 } 1157 node= node.getParent(); 1158 } 1159 return null; 1160 } 1161 1162 private ChildListPropertyDescriptor typeToBodyDeclarationProperty(IType type, CompilationUnit root) throws JavaModelException { 1163 ASTNode typeDeclaration= typeToDeclaration(type, root); 1164 if (typeDeclaration instanceof AbstractTypeDeclaration) 1165 return ((AbstractTypeDeclaration) typeDeclaration).getBodyDeclarationsProperty(); 1166 else if (typeDeclaration instanceof AnonymousClassDeclaration) 1167 return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY; 1168 1169 Assert.isTrue(false); 1170 return null; 1171 } 1172 1173 private RefactoringStatus createWarningAboutCall(IMember enclosing, ASTNode concreteNode, String message) { 1174 String name= JavaElementLabels.getElementLabel(enclosing, JavaElementLabels.ALL_DEFAULT); 1175 String container= JavaElementLabels.getElementLabel(enclosing.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED); 1176 return RefactoringStatus.createWarningStatus(Messages.format(message, new String [] { name, container }), JavaStatusContext.create(enclosing.getCompilationUnit(), concreteNode)); 1177 } 1178 1179 private ITypeBinding getExpressionType(MethodInvocation invocation) { 1180 Expression expression= invocation.getExpression(); 1181 ITypeBinding typeBinding= null; 1182 if (expression == null) { 1183 typeBinding= invocation.resolveMethodBinding().getDeclaringClass(); 1184 } else { 1185 typeBinding= expression.resolveTypeBinding(); 1186 } 1187 1188 Assert.isNotNull(typeBinding, "Type binding of target expression may not be null"); return typeBinding; 1190 } 1191 1192 private IFile[] getAllFilesToModify() { 1193 List cus= new ArrayList (); 1194 cus.addAll(Arrays.asList(fTextChangeManager.getAllCompilationUnits())); 1195 return ResourceUtil.getFiles((ICompilationUnit[]) cus.toArray(new ICompilationUnit[cus.size()])); 1196 } 1197 1198 private boolean isStaticTarget() throws JavaModelException { 1199 return Flags.isStatic(fTargetMethod.getFlags()); 1200 } 1201 1202 private IMember getEnclosingInitialSelectionMember() throws JavaModelException { 1203 return (IMember) fSelectionCompilationUnit.getElementAt(fSelectionStart); 1204 } 1205 1206 private static ASTNode getSelectedNode(ICompilationUnit unit, CompilationUnit root, int offset, int length) { 1207 ASTNode node= null; 1208 try { 1209 if (unit != null) 1210 node= checkNode(NodeFinder.perform(root, offset, length, unit)); 1211 else 1212 node= checkNode(NodeFinder.perform(root, offset, length)); 1213 } catch (JavaModelException e) { 1214 } 1216 if (node != null) 1217 return node; 1218 return checkNode(NodeFinder.perform(root, offset, length)); 1219 } 1220 1221 private static ASTNode checkNode(ASTNode node) { 1222 if (node == null) 1223 return null; 1224 if (node.getNodeType() == ASTNode.SIMPLE_NAME) { 1225 node= node.getParent(); 1226 } else if (node.getNodeType() == ASTNode.EXPRESSION_STATEMENT) { 1227 node= ((ExpressionStatement) node).getExpression(); 1228 } 1229 switch (node.getNodeType()) { 1230 case ASTNode.METHOD_INVOCATION: 1231 case ASTNode.METHOD_DECLARATION: 1232 case ASTNode.SUPER_METHOD_INVOCATION: 1233 return node; 1234 } 1235 return null; 1236 } 1237 1238 1240 private ModifierKeyword getNeededVisibility(IMember whoToAdjust, IMember fromWhereToLook) throws JavaModelException { 1241 return fAdjustor.getVisibilityThreshold(fromWhereToLook, whoToAdjust, new NullProgressMonitor()); 1242 } 1243 1244 private RefactoringStatus adjustVisibility(IMember whoToAdjust, IMember fromWhereToLook, IProgressMonitor monitor) throws CoreException { 1245 return adjustVisibility(whoToAdjust, getNeededVisibility(whoToAdjust, fromWhereToLook), true, monitor); 1246 } 1247 1248 private RefactoringStatus adjustVisibility(IMember whoToAdjust, ModifierKeyword neededVisibility, IProgressMonitor monitor) throws CoreException { 1249 return adjustVisibility(whoToAdjust, neededVisibility, false, monitor); 1250 } 1251 1252 private RefactoringStatus adjustVisibility(IMember whoToAdjust, ModifierKeyword neededVisibility, boolean alsoIncreaseEnclosing, IProgressMonitor monitor) throws CoreException { 1253 1254 Map adjustments; 1255 if (isRewriteKept(whoToAdjust.getCompilationUnit())) 1256 adjustments= fIntermediaryAdjustments; 1257 else 1258 adjustments= new HashMap (); 1259 1260 int existingAdjustments= adjustments.size(); 1261 addAdjustment(whoToAdjust, neededVisibility, adjustments); 1262 1263 if (alsoIncreaseEnclosing) 1264 while (whoToAdjust.getDeclaringType() != null) { 1265 whoToAdjust= whoToAdjust.getDeclaringType(); 1266 addAdjustment(whoToAdjust, neededVisibility, adjustments); 1267 } 1268 1269 boolean hasNewAdjustments= (adjustments.size() - existingAdjustments) > 0; 1270 if (hasNewAdjustments && ( (whoToAdjust.isReadOnly() || whoToAdjust.isBinary()))) 1271 return RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.IntroduceIndirectionRefactoring_cannot_update_binary_target_visibility, new String [] { JavaElementLabels 1272 .getElementLabel(whoToAdjust, JavaElementLabels.ALL_DEFAULT) }), JavaStatusContext.create(whoToAdjust)); 1273 1274 RefactoringStatus status= new RefactoringStatus(); 1275 1276 if (!hasNewAdjustments) 1278 return status; 1279 1280 try { 1281 monitor.beginTask(RefactoringCoreMessages.MemberVisibilityAdjustor_adjusting, 2); 1282 Map rewrites; 1283 if (!isRewriteKept(whoToAdjust.getCompilationUnit())) { 1284 CompilationUnitRewrite rewrite= new CompilationUnitRewrite(whoToAdjust.getCompilationUnit()); 1285 rewrite.setResolveBindings(false); 1286 rewrites= new HashMap (); 1287 rewrites.put(whoToAdjust.getCompilationUnit(), rewrite); 1288 status.merge(rewriteVisibility(adjustments, rewrites, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); 1289 rewrite.attachChange((CompilationUnitChange) fTextChangeManager.get(whoToAdjust.getCompilationUnit()), true, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); 1290 } 1291 } finally { 1292 monitor.done(); 1293 } 1294 return status; 1295 } 1296 1297 private RefactoringStatus rewriteVisibility(Map adjustments, Map rewrites, IProgressMonitor monitor) throws JavaModelException { 1298 RefactoringStatus status= new RefactoringStatus(); 1299 fAdjustor.setRewrites(rewrites); 1300 fAdjustor.setAdjustments(adjustments); 1301 fAdjustor.setStatus(status); 1302 fAdjustor.rewriteVisibility(monitor); 1303 return status; 1304 } 1305 1306 private void addAdjustment(IMember whoToAdjust, ModifierKeyword neededVisibility, Map adjustments) throws JavaModelException { 1307 ModifierKeyword currentVisibility= ModifierKeyword.fromFlagValue(JdtFlags.getVisibilityCode(whoToAdjust)); 1308 if (MemberVisibilityAdjustor.hasLowerVisibility(currentVisibility, neededVisibility) 1309 && MemberVisibilityAdjustor.needsVisibilityAdjustments(whoToAdjust, neededVisibility, adjustments)) 1310 adjustments.put(whoToAdjust, new MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment(whoToAdjust, neededVisibility, 1311 RefactoringStatus.createWarningStatus(Messages.format(MemberVisibilityAdjustor.getMessage(whoToAdjust), new String [] { 1312 MemberVisibilityAdjustor.getLabel(whoToAdjust), MemberVisibilityAdjustor.getLabel(neededVisibility) }), JavaStatusContext 1313 .create(whoToAdjust)))); 1314 } 1315 1316 public RefactoringStatus initialize(final RefactoringArguments arguments) { 1317 if (arguments instanceof JavaRefactoringArguments) { 1318 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 1319 String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 1320 if (handle != null) { 1321 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1322 if (element == null || !element.exists() || element.getElementType() != IJavaElement.METHOD) 1323 return createInputFatalStatus(element, IJavaRefactorings.INTRODUCE_INDIRECTION); 1324 else 1325 fTargetMethod= (IMethod) element; 1326 } else 1327 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 1328 handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1); 1329 if (handle != null) { 1330 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1331 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 1332 return createInputFatalStatus(element, IJavaRefactorings.INTRODUCE_INDIRECTION); 1333 else 1334 fIntermediaryClass= (IType) element; 1335 } else 1336 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + 1)); 1337 final String references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES); 1338 if (references != null) { 1339 fUpdateReferences= Boolean.valueOf(references).booleanValue(); 1340 } else 1341 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES)); 1342 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 1343 if (name != null && !"".equals(name)) return setIntermediaryMethodName(name); 1345 else 1346 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 1347 } else 1348 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 1349 } 1350} 1351 | Popular Tags |