1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collection ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Set ; 22 import java.util.StringTokenizer ; 23 24 import org.eclipse.text.edits.MultiTextEdit; 25 import org.eclipse.text.edits.TextEditGroup; 26 27 import org.eclipse.core.runtime.Assert; 28 import org.eclipse.core.runtime.CoreException; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.NullProgressMonitor; 31 import org.eclipse.core.runtime.OperationCanceledException; 32 import org.eclipse.core.runtime.SubProgressMonitor; 33 34 import org.eclipse.ltk.core.refactoring.Change; 35 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 36 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 37 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 38 39 import org.eclipse.jdt.core.ICompilationUnit; 40 import org.eclipse.jdt.core.IField; 41 import org.eclipse.jdt.core.IJavaElement; 42 import org.eclipse.jdt.core.IJavaProject; 43 import org.eclipse.jdt.core.IMethod; 44 import org.eclipse.jdt.core.JavaModelException; 45 import org.eclipse.jdt.core.dom.AST; 46 import org.eclipse.jdt.core.dom.ASTNode; 47 import org.eclipse.jdt.core.dom.CompilationUnit; 48 import org.eclipse.jdt.core.dom.Expression; 49 import org.eclipse.jdt.core.dom.FieldDeclaration; 50 import org.eclipse.jdt.core.dom.IBinding; 51 import org.eclipse.jdt.core.dom.IMethodBinding; 52 import org.eclipse.jdt.core.dom.ITypeBinding; 53 import org.eclipse.jdt.core.dom.IVariableBinding; 54 import org.eclipse.jdt.core.dom.MethodDeclaration; 55 import org.eclipse.jdt.core.dom.ParameterizedType; 56 import org.eclipse.jdt.core.dom.QualifiedName; 57 import org.eclipse.jdt.core.dom.SimpleName; 58 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 59 import org.eclipse.jdt.core.dom.Type; 60 import org.eclipse.jdt.core.dom.VariableDeclarationExpression; 61 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 62 import org.eclipse.jdt.core.dom.VariableDeclarationStatement; 63 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 64 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; 65 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer; 66 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 67 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 68 import org.eclipse.jdt.core.search.IJavaSearchConstants; 69 import org.eclipse.jdt.core.search.IJavaSearchScope; 70 import org.eclipse.jdt.core.search.SearchPattern; 71 72 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 73 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 74 import org.eclipse.jdt.internal.corext.dom.Bindings; 75 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 76 import org.eclipse.jdt.internal.corext.refactoring.Checks; 77 import org.eclipse.jdt.internal.corext.refactoring.CollectingSearchRequestor; 78 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 79 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 80 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 81 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 82 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 83 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 84 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 85 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 86 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 87 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 88 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; 89 import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2; 90 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator; 91 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompositeOrTypeConstraint; 92 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCollector; 93 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintOperator; 94 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariable; 95 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariableFactory; 96 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ExpressionVariable; 97 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.FullConstraintCreator; 98 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ITypeConstraint; 99 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ParameterTypeVariable; 100 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ReturnTypeVariable; 101 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.SimpleTypeConstraint; 102 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeConstraintFactory; 103 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeVariable; 104 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 105 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 106 import org.eclipse.jdt.internal.corext.util.Messages; 107 import org.eclipse.jdt.internal.corext.util.SearchUtils; 108 109 import org.eclipse.jdt.ui.JavaElementLabels; 110 111 import org.eclipse.jdt.internal.ui.JavaPlugin; 112 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; 113 114 117 public class ChangeTypeRefactoring extends ScriptableRefactoring { 118 119 private static final String ATTRIBUTE_TYPE= "type"; 121 private final Map fConstraintCache; 122 125 private int fSelectionStart; 126 127 130 private int fSelectionLength; 131 132 135 private int fEffectiveSelectionStart; 136 137 140 private int fEffectiveSelectionLength; 141 142 145 private ICompilationUnit fCu; 146 147 153 private IMethodBinding fMethodBinding; 154 155 160 private int fParamIndex; 161 162 165 private String fParamName; 166 167 171 private IVariableBinding fFieldBinding; 172 173 176 private ICompilationUnit[] fAffectedUnits; 177 178 183 private Collection fRelevantVars; 184 185 189 private final Collection fValidTypes; 190 191 194 private Collection fRelevantConstraints; 195 196 199 private Collection fAllConstraints; 200 201 204 private String fSelectedTypeName; 205 206 209 private ITypeBinding fSelectedType; 210 211 214 private Map fCuToSearchResultGroup= new HashMap (); 215 216 217 220 private ITypeBinding fObject; 221 222 public ITypeBinding getObject(){ 223 return fObject; 224 } 225 226 229 private static final boolean DEBUG= false; 230 231 private ConstraintVariable fCv; 232 private IBinding fSelectionBinding; 233 private ITypeBinding fSelectionTypeBinding; 234 private ConstraintCollector fCollector; 235 236 public ChangeTypeRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength) { 237 this(cu, selectionStart, selectionLength, null); 238 } 239 240 243 public ChangeTypeRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength, String selectedType) { 244 Assert.isTrue(selectionStart >= 0); 245 Assert.isTrue(selectionLength >= 0); 246 247 fSelectionStart= selectionStart; 248 fSelectionLength= selectionLength; 249 250 fEffectiveSelectionStart= selectionStart; 251 fEffectiveSelectionLength= selectionLength; 252 253 fCu= cu; 254 255 if (selectedType != null) 256 fSelectedTypeName= selectedType; 257 258 fConstraintCache= new HashMap (); 259 fValidTypes= new HashSet (); 260 } 261 262 264 267 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { 268 if (fCu == null || !fCu.isStructureKnown()) 269 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection); 270 return checkSelection(new SubProgressMonitor(pm, 1)); 271 } 272 273 private void setSelectionRanges(Expression exp){ 274 fEffectiveSelectionStart= exp.getStartPosition(); 275 fEffectiveSelectionLength= exp.getLength(); 276 fSelectionBinding= ExpressionVariable.resolveBinding(exp); 277 setOriginalType(exp.resolveTypeBinding()); 278 } 279 280 284 private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaModelException { 285 try { 286 pm.beginTask("", 5); 288 ASTNode node= getTargetNode(fCu, fSelectionStart, fSelectionLength); 289 if (DEBUG) { 290 System.out.println( 291 "selection: [" + fSelectionStart 293 + "," + (fSelectionStart + fSelectionLength) 295 + "] in " + fCu.getElementName()); 297 System.out.println("node= " + node + ", type= " + node.getClass().getName()); } 299 300 TypeConstraintFactory typeConstraintFactory = new TypeConstraintFactory(){ 301 public boolean filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator o){ 302 if (o.isStrictSubtypeOperator()) return true; 304 if (v1.getBinding() != null && v2.getBinding() != null 306 && ! Bindings.equals(v1.getBinding(), fSelectionTypeBinding) 307 && ! Bindings.equals(v2.getBinding(), fSelectionTypeBinding)) { 308 if (PRINT_STATS) fNrFiltered++; 309 return true; 310 } 311 return super.filter(v1, v2, o); 312 } 313 }; 314 fCollector= new ConstraintCollector(new FullConstraintCreator(new ConstraintVariableFactory(), typeConstraintFactory)); 315 String selectionValid= determineSelection(node); 316 if (selectionValid != null){ 317 if (DEBUG){ 318 System.out.println("invalid selection: " + selectionValid); } 320 return RefactoringStatus.createFatalErrorStatus(selectionValid); 321 } 322 323 if (fMethodBinding != null) { 324 IMethod selectedMethod= (IMethod) fMethodBinding.getJavaElement(); 325 if (selectedMethod == null){ 326 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported); 327 } 328 } 329 330 pm.worked(1); 331 332 RefactoringStatus result= new RefactoringStatus(); 333 334 if (DEBUG){ 335 System.out.println("fSelectionTypeBinding: " + fSelectionTypeBinding.getName()); } 337 338 if (fSelectionTypeBinding.isArray()){ 340 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported); 341 } 342 if (fSelectionTypeBinding.isPrimitive()){ 343 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_primitivesNotSupported); 344 } 345 if (checkOverriddenBinaryMethods()) 346 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnBinary); 347 348 if (fSelectionTypeBinding.isLocal()){ 349 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_localTypesNotSupported); 350 } 351 352 if (fFieldBinding != null && fFieldBinding.getDeclaringClass().isLocal()){ 353 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported); 354 } 355 356 if (fSelectionTypeBinding.isTypeVariable()){ 357 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_typeParametersNotSupported); 358 } 359 360 if (fSelectionTypeBinding.isEnum()){ 361 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_enumsNotSupported); 362 } 363 364 pm.worked(1); 365 366 if (fSelectedType != null){ computeValidTypes(new NullProgressMonitor()); 368 } 369 return result; 370 } finally { 371 pm.done(); 372 } 373 } 374 375 private boolean checkOverriddenBinaryMethods() throws JavaModelException { 376 if (fMethodBinding != null){ 377 Set declaringSupertypes= getDeclaringSuperTypes(fMethodBinding); 378 for (Iterator iter= declaringSupertypes.iterator(); iter.hasNext();) { 379 ITypeBinding superType= (ITypeBinding) iter.next(); 380 IMethodBinding overriddenMethod= findMethod(fMethodBinding, superType); 381 Assert.isNotNull(overriddenMethod); IMethod iMethod= (IMethod) overriddenMethod.getJavaElement(); 383 if (iMethod.isBinary()){ 384 return true; 385 } 386 } 387 } 388 return false; 389 } 390 391 private static IMethodBinding findMethod(IMethodBinding methodBinding, ITypeBinding type) { 393 if (methodBinding.getDeclaringClass().equals(type)) 394 return methodBinding; 395 return Bindings.findOverriddenMethodInType(type, methodBinding); 396 } 397 398 private static Set getDeclaringSuperTypes(IMethodBinding methodBinding) { 400 ITypeBinding[] allSuperTypes= Bindings.getAllSuperTypes(methodBinding.getDeclaringClass()); 401 Set result= new HashSet (); 402 for (int i= 0; i < allSuperTypes.length; i++) { 403 ITypeBinding type= allSuperTypes[i]; 404 if (findMethod(methodBinding, type) != null) 405 result.add(type); 406 } 407 return result; 408 } 409 410 414 public Collection computeValidTypes(IProgressMonitor pm) { 415 416 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions, 100); 417 418 try { 419 fCv= findConstraintVariableForSelectedNode(new SubProgressMonitor(pm, 3)); 420 if (DEBUG) System.out.println("selected CV: " + fCv + " (" + fCv.getClass().getName() + ")"); 424 if (pm.isCanceled()) 425 throw new OperationCanceledException(); 426 fRelevantVars= findRelevantConstraintVars(fCv, new SubProgressMonitor(pm, 50)); 427 428 if (DEBUG) 429 printCollection("relevant vars:", fRelevantVars); 431 if (pm.isCanceled()) 432 throw new OperationCanceledException(); 433 fRelevantConstraints= findRelevantConstraints(fRelevantVars, new SubProgressMonitor(pm, 30)); 434 435 if (pm.isCanceled()) 436 throw new OperationCanceledException(); 437 fValidTypes.addAll(computeValidTypes(fSelectionTypeBinding, fRelevantVars, 438 fRelevantConstraints, new SubProgressMonitor(pm, 20))); 439 440 if (DEBUG) 441 printCollection("valid types:", getValidTypeNames()); } catch (CoreException e) { 443 JavaPlugin.logErrorMessage("Error occurred during computation of valid types: " + e.toString()); fValidTypes.clear(); } 446 447 pm.done(); 448 449 return fValidTypes; 450 } 451 452 453 456 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { 457 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions, 1); 458 459 RefactoringStatus result= Checks.validateModifiesFiles( 460 ResourceUtil.getFiles(fAffectedUnits), getValidationContext()); 461 462 pm.done(); 463 return result; 464 } 465 469 public Change createChange(IProgressMonitor pm) throws CoreException { 470 pm.beginTask(RefactoringCoreMessages.ChangeTypeMessages_CreateChangesForChangeType, 1); 471 try { 472 Map relevantVarsByUnit= new HashMap (); 473 groupChangesByCompilationUnit(relevantVarsByUnit); 474 final Map arguments= new HashMap (); 475 String project= null; 476 IJavaProject javaProject= fCu.getJavaProject(); 477 if (javaProject != null) 478 project= javaProject.getElementName(); 479 final String description= RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description_short; 480 final String header= Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description, new String [] { BindingLabelProvider.getBindingLabel(fSelectionBinding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(fSelectedType, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 481 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 482 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_original_element_pattern, BindingLabelProvider.getBindingLabel(fSelectionBinding, JavaElementLabels.ALL_FULLY_QUALIFIED))); 483 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_original_type_pattern, BindingLabelProvider.getBindingLabel(getOriginalType(), JavaElementLabels.ALL_FULLY_QUALIFIED))); 484 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_refactored_type_pattern, BindingLabelProvider.getBindingLabel(fSelectedType, JavaElementLabels.ALL_FULLY_QUALIFIED))); 485 final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.GENERALIZE_TYPE, project, description, comment.asString(), arguments, (RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT)); 486 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fCu)); 487 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION, new Integer (fSelectionStart).toString() + " " + new Integer (fSelectionLength).toString()); arguments.put(ATTRIBUTE_TYPE, fSelectedType.getQualifiedName()); 489 final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ChangeTypeRefactoring_allChanges); 490 for (Iterator it= relevantVarsByUnit.keySet().iterator(); it.hasNext();) { 491 ICompilationUnit icu= (ICompilationUnit) it.next(); 492 Set cVars= (Set ) relevantVarsByUnit.get(icu); 493 CompilationUnitChange cuChange= new CompilationUnitChange(getName(), icu); 494 addAllChangesFor(icu, cVars, cuChange); 495 result.add(cuChange); 496 pm.worked(1); 497 if (pm.isCanceled()) 498 throw new OperationCanceledException(); 499 } 500 return result; 501 } finally { 502 pm.done(); 503 } 504 } 505 506 509 private void addAllChangesFor(ICompilationUnit icu, Set vars, CompilationUnitChange unitChange) throws CoreException { 510 CompilationUnit unit= new RefactoringASTParser(AST.JLS3).parse(icu, false); 511 ASTRewrite unitRewriter= ASTRewrite.create(unit.getAST()); 512 MultiTextEdit root= new MultiTextEdit(); 513 unitChange.setEdit(root); 515 String typeName= updateImports(unit, root); 516 updateCu(unit, vars, unitChange, unitRewriter, typeName); 517 root.addChild(unitRewriter.rewriteAST()); 518 } 519 520 private class SourceRangeComputer extends TargetSourceRangeComputer { 521 public SourceRange computeSourceRange(ASTNode node) { 522 return new SourceRange(node.getStartPosition(),node.getLength()); 523 } 524 } 525 526 private void updateCu(CompilationUnit unit, Set vars, CompilationUnitChange unitChange, 527 ASTRewrite unitRewriter, String typeName) throws JavaModelException { 528 529 unitRewriter.setTargetSourceRangeComputer(new SourceRangeComputer()); 531 532 for (Iterator it=vars.iterator(); it.hasNext(); ){ 533 ConstraintVariable cv = (ConstraintVariable)it.next(); 534 ASTNode decl= findDeclaration(unit, cv); 535 if ((decl instanceof SimpleName || decl instanceof QualifiedName) && cv instanceof ExpressionVariable) { 536 ASTNode gp= decl.getParent().getParent(); 537 updateType(unit, getType(gp), unitChange, unitRewriter, typeName); } else if (decl instanceof MethodDeclaration || decl instanceof FieldDeclaration) { 539 updateType(unit, getType(decl), unitChange, unitRewriter, typeName); } else if (decl instanceof ParameterizedType){ 541 updateType(unit, getType(decl), unitChange, unitRewriter, typeName); 542 } 543 } 544 } 545 546 private void updateType(CompilationUnit cu, Type oldType, CompilationUnitChange unitChange, 547 ASTRewrite unitRewriter, String typeName) { 548 549 String oldName= fSelectionTypeBinding.getName(); 550 String description= Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_typeChange, new String [] {oldName, typeName}); 551 TextEditGroup gd= new TextEditGroup(description); 552 AST ast= cu.getAST(); 553 554 ASTNode nodeToReplace= oldType; 555 if (fSelectionTypeBinding.isParameterizedType() && !fSelectionTypeBinding.isRawType()){ 556 if (oldType.isSimpleType()){ 557 nodeToReplace= oldType.getParent(); 558 } 559 } 560 561 Assert.isTrue(fSelectedType.isClass() || fSelectedType.isInterface()); 563 564 Type newType= null; 565 if (!fSelectedType.isParameterizedType()){ 566 newType= ast.newSimpleType(ASTNodeFactory.newName(ast, typeName)); 567 } else { 568 newType= createParameterizedType(ast, fSelectedType); 569 } 570 571 unitRewriter.replace(nodeToReplace, newType, gd); 572 unitChange.addTextEditGroup(gd); 573 } 574 575 579 private Type createParameterizedType(AST ast, ITypeBinding typeBinding){ 580 if (typeBinding.isParameterizedType() && !typeBinding.isRawType()){ 581 Type baseType= ast.newSimpleType(ASTNodeFactory.newName(ast, typeBinding.getErasure().getName())); 582 ParameterizedType newType= ast.newParameterizedType(baseType); 583 for (int i=0; i < typeBinding.getTypeArguments().length; i++){ 584 ITypeBinding typeArg= typeBinding.getTypeArguments()[i]; 585 Type argType= createParameterizedType(ast, typeArg); newType.typeArguments().add(argType); 587 } 588 return newType; 589 } else { 590 if (!typeBinding.isTypeVariable()){ 591 return ast.newSimpleType(ASTNodeFactory.newName(ast, typeBinding.getErasure().getName())); 592 } else { 593 return ast.newSimpleType(ast.newSimpleName(typeBinding.getName())); 594 } 595 } 596 } 597 598 599 600 private void groupChangesByCompilationUnit(Map relevantVarsByUnit) throws JavaModelException { 601 for (Iterator it= fRelevantVars.iterator(); it.hasNext();) { 602 ConstraintVariable cv= (ConstraintVariable) it.next(); 603 if (!(cv instanceof ExpressionVariable) && !(cv instanceof ReturnTypeVariable)){ 604 continue; 605 } 606 ICompilationUnit icu = null; 607 if (cv instanceof ExpressionVariable) { 608 ExpressionVariable ev = (ExpressionVariable)cv; 609 icu = ev.getCompilationUnitRange().getCompilationUnit(); 610 } else if (cv instanceof ReturnTypeVariable){ 611 ReturnTypeVariable rtv = (ReturnTypeVariable)cv; 612 IMethodBinding mb= rtv.getMethodBinding(); 613 icu= ((IMethod) mb.getJavaElement()).getCompilationUnit(); 614 } 615 if (!relevantVarsByUnit.containsKey(icu)){ 616 relevantVarsByUnit.put(icu, new HashSet ()); 617 } 618 ((Set )relevantVarsByUnit.get(icu)).add(cv); 619 } 620 } 621 622 private ASTNode findDeclaration(CompilationUnit root, ConstraintVariable cv) throws JavaModelException { 623 624 if (fFieldBinding != null){ 625 IField f= (IField) fFieldBinding.getJavaElement(); 626 return ASTNodeSearchUtil.getFieldDeclarationNode(f, root); 627 } 628 629 if (cv instanceof ExpressionVariable){ 630 for (Iterator iter= fAllConstraints.iterator(); iter.hasNext();) { 631 ITypeConstraint constraint= (ITypeConstraint) iter.next(); 632 if (constraint.isSimpleTypeConstraint()){ 633 SimpleTypeConstraint stc= (SimpleTypeConstraint)constraint; 634 if (stc.isDefinesConstraint() && stc.getLeft().equals(cv)){ 635 ConstraintVariable right= stc.getRight(); 636 if (right instanceof TypeVariable){ 637 TypeVariable typeVariable= (TypeVariable)right; 638 return NodeFinder.perform(root, typeVariable.getCompilationUnitRange().getSourceRange()); 639 } 640 } 641 } 642 } 643 } else if (cv instanceof ReturnTypeVariable) { 644 ReturnTypeVariable rtv= (ReturnTypeVariable) cv; 645 IMethodBinding mb= rtv.getMethodBinding(); 646 IMethod im= (IMethod) mb.getJavaElement(); 647 return ASTNodeSearchUtil.getMethodDeclarationNode(im, root); 648 } 649 return null; 650 } 651 652 private static Type getType(ASTNode node) { 653 switch(node.getNodeType()){ 654 case ASTNode.SINGLE_VARIABLE_DECLARATION: 655 return ((SingleVariableDeclaration) node).getType(); 656 case ASTNode.FIELD_DECLARATION: 657 return ((FieldDeclaration) node).getType(); 658 case ASTNode.VARIABLE_DECLARATION_STATEMENT: 659 return ((VariableDeclarationStatement) node).getType(); 660 case ASTNode.METHOD_DECLARATION: 661 return ((MethodDeclaration)node).getReturnType2(); 662 case ASTNode.PARAMETERIZED_TYPE: 663 return ((ParameterizedType)node).getType(); 664 default: 665 Assert.isTrue(false); 666 return null; 667 } 668 } 669 670 673 public String getName() { 674 return RefactoringCoreMessages.ChangeTypeRefactoring_name; 675 } 676 677 681 686 private String determineSelection(ASTNode node) { 687 if (node == null) { 688 return RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection; 689 } else { 690 691 if (DEBUG) System.out.println("node nodeType= " + node.getClass().getName()); if (DEBUG) System.out.println("parent nodeType= " + node.getParent().getClass().getName()); if (DEBUG) System.out.println("GrandParent nodeType= " + node.getParent().getParent().getClass().getName()); 695 ASTNode parent= node.getParent(); 696 ASTNode grandParent= parent.getParent(); 697 if (grandParent == null) 698 return nodeTypeNotSupported(); 699 700 if (grandParent.getNodeType() == ASTNode.PARAMETERIZED_TYPE){ 702 node= grandParent; 703 } 704 705 ASTNode current= null; 707 if (node.getNodeType() == ASTNode.QUALIFIED_NAME){ 708 current= node; 709 while (current.getNodeType() == ASTNode.QUALIFIED_NAME){ 710 current= current.getParent(); 711 } 712 if (current.getNodeType() != ASTNode.SIMPLE_TYPE){ 713 return nodeTypeNotSupported(); 714 } 715 node= current.getParent(); 716 } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME){ 717 current= parent; 718 while (current.getNodeType() == ASTNode.QUALIFIED_NAME){ 719 current= current.getParent(); 720 } 721 if (current.getNodeType() != ASTNode.SIMPLE_TYPE){ 722 return nodeTypeNotSupported(); 723 } 724 node= current.getParent(); 725 } 726 727 fObject= node.getAST().resolveWellKnownType("java.lang.Object"); switch (node.getNodeType()) { 729 case ASTNode.SIMPLE_NAME : 730 return simpleNameSelected((SimpleName)node); 731 case ASTNode.VARIABLE_DECLARATION_STATEMENT : 732 return variableDeclarationStatementSelected((VariableDeclarationStatement) node); 733 case ASTNode.FIELD_DECLARATION : 734 return fieldDeclarationSelected((FieldDeclaration) node); 735 case ASTNode.SINGLE_VARIABLE_DECLARATION : 736 return singleVariableDeclarationSelected((SingleVariableDeclaration) node); 737 case ASTNode.PARAMETERIZED_TYPE: 738 return parameterizedTypeSelected((ParameterizedType) node); 739 default : 740 return nodeTypeNotSupported(); 741 } 742 } 743 } 744 747 private static String nodeTypeNotSupported() { 748 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType; 749 } 750 751 754 private String singleVariableDeclarationSelected(SingleVariableDeclaration svd) { 755 SimpleName name = svd.getName(); 756 setSelectionRanges(name); 757 return simpleNameSelected(name); 758 } 759 760 763 private String parameterizedTypeSelected(ParameterizedType pt) { 764 ASTNode parent= pt.getParent(); 765 if (parent.getNodeType() == ASTNode.METHOD_DECLARATION){ 766 fMethodBinding= ((MethodDeclaration)parent).resolveBinding(); 767 fParamIndex= -1; 768 fEffectiveSelectionStart= pt.getStartPosition(); 769 fEffectiveSelectionLength= pt.getLength(); 770 setOriginalType(pt.resolveBinding()); 771 } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION){ 772 return singleVariableDeclarationSelected((SingleVariableDeclaration)parent); 773 } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){ 774 return variableDeclarationStatementSelected((VariableDeclarationStatement)parent); 775 } else if (parent.getNodeType() == ASTNode.FIELD_DECLARATION){ 776 return fieldDeclarationSelected((FieldDeclaration)parent); 777 } else { 778 return nodeTypeNotSupported(); 779 } 780 return null; 781 } 782 783 786 private String variableDeclarationStatementSelected(VariableDeclarationStatement vds) { 787 if (vds.fragments().size() != 1) { 788 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 789 } else { 790 VariableDeclarationFragment elem= (VariableDeclarationFragment) vds.fragments().iterator().next(); 791 SimpleName name= elem.getName(); 792 setSelectionRanges(name); 793 return simpleNameSelected(name); 794 } 795 } 796 797 800 private String fieldDeclarationSelected(FieldDeclaration fieldDeclaration) { 801 if (fieldDeclaration.fragments().size() != 1) { 802 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 803 } else { 804 VariableDeclarationFragment elem= (VariableDeclarationFragment) fieldDeclaration.fragments().iterator().next(); 805 fFieldBinding= elem.resolveBinding(); 806 SimpleName name= elem.getName(); 807 setSelectionRanges(name); 808 return simpleNameSelected(name); 809 } 810 } 811 812 815 private String simpleNameSelected(SimpleName simpleName) { 816 ASTNode parent= simpleName.getParent(); 817 ASTNode grandParent= parent.getParent(); 818 819 if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){ 820 VariableDeclarationStatement vds= (VariableDeclarationStatement)parent; 821 if (vds.fragments().size() > 1){ 822 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 823 } 824 } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_FRAGMENT) { 825 if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){ 826 VariableDeclarationStatement vds= (VariableDeclarationStatement)grandParent; 827 if (vds.fragments().size() > 1) { 828 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 829 } 830 setSelectionRanges(simpleName); 831 } else if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION) { 832 VariableDeclarationExpression vde= (VariableDeclarationExpression)grandParent; 833 if (vde.fragments().size() > 1) { 834 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 835 } 836 setSelectionRanges(simpleName); 837 } else if (grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) { 838 FieldDeclaration fd= (FieldDeclaration)grandParent; 839 if (fd.fragments().size() > 1){ 840 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported; 841 } 842 VariableDeclarationFragment fragment = (VariableDeclarationFragment)parent; 843 fFieldBinding= fragment.resolveBinding(); 844 setSelectionRanges(fragment.getName()); 845 } else { 846 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType; 847 } 848 } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION) { 849 SingleVariableDeclaration singleVariableDeclaration= (SingleVariableDeclaration) parent; 850 if ((grandParent.getNodeType() == ASTNode.METHOD_DECLARATION)) { 851 fMethodBinding= ((MethodDeclaration)grandParent).resolveBinding(); 852 setOriginalType(simpleName.resolveTypeBinding()); 853 fParamIndex= ((MethodDeclaration)grandParent).parameters().indexOf(parent); 854 fParamName= singleVariableDeclaration.getName().getIdentifier(); 855 } else { 856 setSelectionRanges(singleVariableDeclaration.getName()); 857 } 858 } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && (grandParent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION)) { 859 ASTNode greatGrandParent= grandParent.getParent(); 860 SingleVariableDeclaration singleVariableDeclaration= (SingleVariableDeclaration) grandParent; 861 if (singleVariableDeclaration.getExtraDimensions() > 0) { 862 return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported; 863 } 864 if (greatGrandParent != null && greatGrandParent.getNodeType() == ASTNode.METHOD_DECLARATION) { 865 fMethodBinding= ((MethodDeclaration)greatGrandParent).resolveBinding(); 866 fParamIndex= ((MethodDeclaration)greatGrandParent).parameters().indexOf(grandParent); 867 fParamName= singleVariableDeclaration.getName().getIdentifier(); 868 setSelectionRanges(simpleName); 869 } else { 870 setSelectionRanges(singleVariableDeclaration.getName()); 871 } 872 } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && grandParent.getNodeType() == ASTNode.METHOD_DECLARATION) { 873 fMethodBinding= ((MethodDeclaration)grandParent).resolveBinding(); 874 setOriginalType(fMethodBinding.getReturnType()); 875 fParamIndex= -1; 876 } else if (parent.getNodeType() == ASTNode.METHOD_DECLARATION && 877 grandParent.getNodeType() == ASTNode.TYPE_DECLARATION) { 878 MethodDeclaration methodDeclaration= (MethodDeclaration)parent; 879 if (methodDeclaration.getName().equals(simpleName) || methodDeclaration.thrownExceptions().contains(simpleName)){ 880 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType; 881 } 882 fMethodBinding= ((MethodDeclaration)parent).resolveBinding(); 883 fParamIndex= -1; 884 } else if ( 885 parent.getNodeType() == ASTNode.SIMPLE_TYPE && (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT)) { 886 return variableDeclarationStatementSelected((VariableDeclarationStatement) grandParent); 887 } else if (parent.getNodeType() == ASTNode.CAST_EXPRESSION) { 888 ASTNode decl= findDeclaration(parent.getRoot(), fSelectionStart, fSelectionLength+1); 889 VariableDeclarationFragment fragment= (VariableDeclarationFragment)decl; 890 SimpleName name = fragment.getName(); 891 setSelectionRanges(name); 892 } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && 893 grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) { 894 return fieldDeclarationSelected((FieldDeclaration) grandParent); 895 } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && 896 grandParent.getNodeType() == ASTNode.ARRAY_TYPE){ 897 return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported; 898 } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME){ 899 setSelectionRanges(simpleName); 900 } else { 901 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType; 902 } 903 return null; 904 } 905 906 913 916 private ConstraintVariable findConstraintVariableForSelectedNode(IProgressMonitor pm) { 917 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 100); 918 ICompilationUnit[] cus= { fCu }; 920 if (DEBUG){ 921 System.out.println("Effective selection: " + fEffectiveSelectionStart + "/" + fEffectiveSelectionLength); } 923 924 Collection allConstraints= getConstraints(cus, new SubProgressMonitor(pm, 50)); 925 926 IProgressMonitor subMonitor= new SubProgressMonitor(pm, 50); 927 subMonitor.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, allConstraints.size()); 928 for (Iterator it= allConstraints.iterator(); it.hasNext(); ) { 929 subMonitor.worked(1); 930 ITypeConstraint tc= (ITypeConstraint)it.next(); 931 if (! (tc instanceof SimpleTypeConstraint)) 932 continue; 933 SimpleTypeConstraint stc= (SimpleTypeConstraint) tc; 934 if (matchesSelection(stc.getLeft())) 935 return stc.getLeft(); 936 if (matchesSelection(stc.getRight())) 937 return stc.getRight(); 938 } 939 subMonitor.done(); 940 pm.done(); 941 Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_noMatchingConstraintVariable); 942 return null; 943 } 944 945 948 private boolean matchesSelection(ConstraintVariable cv){ 949 if (cv instanceof ExpressionVariable){ 950 ExpressionVariable ev= (ExpressionVariable)cv; 951 return (fSelectionBinding != null && Bindings.equals(fSelectionBinding, ev.getExpressionBinding())); 952 } else if (cv instanceof ParameterTypeVariable){ 953 ParameterTypeVariable ptv = (ParameterTypeVariable)cv; 954 if (fMethodBinding != null && Bindings.equals(ptv.getMethodBinding(), fMethodBinding) && 955 ptv.getParameterIndex() == fParamIndex){ 956 return true; 957 } 958 } else if (cv instanceof ReturnTypeVariable){ 959 ReturnTypeVariable rtv = (ReturnTypeVariable)cv; 960 if (fMethodBinding != null && Bindings.equals(rtv.getMethodBinding(), fMethodBinding) && 961 fParamIndex == -1){ 962 return true; 963 } 964 } 965 return false; 966 } 967 968 974 private Collection findRelevantConstraintVars(ConstraintVariable cv, IProgressMonitor pm) throws CoreException { 975 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 150); 976 Collection result= new HashSet (); 977 result.add(cv); 978 ICompilationUnit[] cus= collectAffectedUnits(new SubProgressMonitor(pm, 50)); 979 Collection allConstraints= getConstraints(cus, new SubProgressMonitor(pm, 50)); 980 981 List workList= new ArrayList (result); 982 while(! workList.isEmpty()){ 983 984 pm.worked(10); 985 986 ConstraintVariable first= (ConstraintVariable)workList.remove(0); 987 for (Iterator iter= allConstraints.iterator(); iter.hasNext();) { 988 pm.worked(1); 989 ITypeConstraint typeConstraint= (ITypeConstraint) iter.next(); 990 if (! typeConstraint.isSimpleTypeConstraint()) 991 continue; 992 SimpleTypeConstraint stc= (SimpleTypeConstraint)typeConstraint; 993 if (! stc.isDefinesConstraint() && ! stc.isEqualsConstraint()) 994 continue; 995 ConstraintVariable match= match(first, stc.getLeft(), stc.getRight()); 996 if (match instanceof ExpressionVariable 997 || match instanceof ParameterTypeVariable 998 || match instanceof ReturnTypeVariable){ 999 if (! result.contains(match)){ 1000 workList.add(match); 1001 result.add(match); 1002 } 1003 } 1004 } 1005 } 1006 1007 pm.done(); 1008 1009 return result; 1010 } 1011 private static ConstraintVariable match(ConstraintVariable matchee, ConstraintVariable left, ConstraintVariable right) { 1012 if (matchee.equals(left)) 1013 return right; 1014 if (matchee.equals(right)) 1015 return left; 1016 return null; 1017 } 1018 1019 1022 private Collection findRelevantConstraints(Collection relevantConstraintVars, 1023 IProgressMonitor pm) throws CoreException { 1024 1025 ICompilationUnit[] cus= collectAffectedUnits(new SubProgressMonitor(pm, 100)); 1026 1027 fAllConstraints= getConstraints(cus, new SubProgressMonitor(pm, 900)); 1028 1029 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 1000 + fAllConstraints.size()); 1030 1031 1032 if (DEBUG) printCollection("type constraints: ", fAllConstraints); Collection result= new ArrayList (); 1034 for (Iterator it= fAllConstraints.iterator(); it.hasNext(); ) { 1035 ITypeConstraint tc= (ITypeConstraint)it.next(); 1036 if (tc.isSimpleTypeConstraint()) { 1037 SimpleTypeConstraint stc= (SimpleTypeConstraint) tc; 1038 if (stc.isDefinesConstraint() || stc.isEqualsConstraint()) 1039 continue; 1040 if (stc.getLeft().equals(stc.getRight())) 1041 continue; 1042 if (isNull(stc.getLeft())) 1043 continue; 1044 if (relevantConstraintVars.contains(stc.getLeft()) || relevantConstraintVars.contains(stc.getRight())) 1045 result.add(tc); 1046 } else { 1047 CompositeOrTypeConstraint cotc= (CompositeOrTypeConstraint) tc; 1048 ITypeConstraint[] components= cotc.getConstraints(); 1049 for (int i= 0; i < components.length; i++) { 1050 ITypeConstraint component= components[i]; 1051 SimpleTypeConstraint simpleComponent= (SimpleTypeConstraint) component; 1052 if (relevantConstraintVars.contains(simpleComponent.getLeft())) 1053 result.add(tc); 1054 } 1055 } 1056 pm.worked(1); 1057 } 1058 if (DEBUG) 1059 printCollection("selected constraints: ", result); pm.done(); 1061 return result; 1062 } 1063 1064 1067 private static ASTNode findDeclaration(final ASTNode root, final int start, final int length){ 1068 ASTNode node= NodeFinder.perform(root, start, length); 1069 Assert.isTrue(node instanceof SimpleName, String.valueOf(node.getNodeType())); 1070 Assert.isTrue(root instanceof CompilationUnit, String.valueOf(root.getNodeType())); 1071 return ((CompilationUnit)root).findDeclaringNode(((SimpleName)node).resolveBinding()); 1072 } 1073 1074 static String print(Collection types){ 1076 if (types.isEmpty()) 1077 return "{ }"; String result = "{ "; for (Iterator it=types.iterator(); it.hasNext(); ){ 1080 ITypeBinding type= (ITypeBinding)it.next(); 1081 result += type.getQualifiedName(); 1082 if (it.hasNext()){ 1083 result += ", "; } else { 1085 result += " }"; } 1087 } 1088 return result; 1089 } 1090 1091 1092 1095 private Collection computeValidTypes(ITypeBinding originalType, 1096 Collection relevantVars, 1097 Collection relevantConstraints, 1098 IProgressMonitor pm) throws JavaModelException { 1099 1100 Collection result= new HashSet (); 1101 IJavaProject project= fCu.getJavaProject(); 1102 1103 Collection allTypes = new HashSet (); 1104 allTypes.addAll(getAllSuperTypes(originalType)); 1105 1106 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, allTypes.size()); 1107 1108 for (Iterator it= allTypes.iterator(); it.hasNext(); ) { 1109 ITypeBinding type= (ITypeBinding)it.next(); 1110 if (isValid(project, type, relevantVars, relevantConstraints, new SubProgressMonitor(pm, 1))) { 1111 result.add(type); 1112 } 1113 } 1114 result.remove(originalType); 1116 1117 1120 pm.done(); 1121 1122 return result; 1123 } 1124 1125 1128 private boolean isValid(IJavaProject project, 1129 ITypeBinding type, 1130 Collection relevantVars, 1131 Collection constraints, 1132 IProgressMonitor pm) throws JavaModelException { 1133 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, constraints.size()); 1134 for (Iterator it= constraints.iterator(); it.hasNext(); ) { 1135 ITypeConstraint tc= (ITypeConstraint)it.next(); 1136 if (tc instanceof SimpleTypeConstraint) { 1137 if (!(isValidSimpleConstraint(project, type, relevantVars, (SimpleTypeConstraint) tc))) 1138 return false; 1139 } else if (tc instanceof CompositeOrTypeConstraint) { 1140 if (!(isValidOrConstraint(project, type, relevantVars, (CompositeOrTypeConstraint) tc))) 1141 return false; 1142 } 1143 pm.worked(1); 1144 } 1145 pm.done(); 1146 return true; 1147 } 1148 1149 private boolean isValidSimpleConstraint(IJavaProject project, ITypeBinding type, 1150 Collection relevantVars, 1151 SimpleTypeConstraint stc) throws JavaModelException{ 1152 if (relevantVars.contains(stc.getLeft())) { if (!isSubTypeOf(type, findType(stc.getRight()))) { 1154 return false; 1155 } 1156 } 1157 return true; 1158 } 1159 1160 private boolean isValidOrConstraint(IJavaProject project, ITypeBinding type, 1161 Collection relevantVars, 1162 CompositeOrTypeConstraint cotc) throws JavaModelException{ 1163 ITypeConstraint[] components= cotc.getConstraints(); 1164 for (int i= 0; i < components.length; i++) { 1165 if (components[i] instanceof SimpleTypeConstraint) { 1166 SimpleTypeConstraint sc= (SimpleTypeConstraint) components[i]; 1167 if (relevantVars.contains(sc.getLeft())) { if (isSubTypeOf(type, findType(sc.getRight()))) 1169 return true; 1170 } else if (relevantVars.contains(sc.getRight())) { if (isSubTypeOf(findType(sc.getLeft()), type)) 1172 return true; 1173 } 1174 } 1175 } 1176 return false; 1177 } 1178 1179 1180 private ITypeBinding findType(ConstraintVariable cv) { 1181 return cv.getBinding(); 1182 } 1183 1184 1187 private Collection getConstraints(ICompilationUnit[] referringCus, IProgressMonitor pm) { 1188 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, referringCus.length); 1189 Collection result= new ArrayList (); 1190 for (int i= 0; i < referringCus.length; i++) { 1191 result.addAll(getConstraints(referringCus[i])); 1192 pm.worked(1); 1193 if (pm.isCanceled()) 1194 throw new OperationCanceledException(); 1195 } 1196 pm.done(); 1197 return result; 1198 } 1199 1200 private List getConstraints(ICompilationUnit unit) { 1201 if (fConstraintCache.containsKey(unit)) 1202 return (List ) fConstraintCache.get(unit); 1203 1204 CompilationUnit cu= ASTCreator.createAST(unit, null); 1205 1206 if (fMethodBinding != null && fCuToSearchResultGroup.containsKey(unit)){ 1208 SearchResultGroup group= (SearchResultGroup) fCuToSearchResultGroup.get(unit); 1209 ASTNode[] nodes= ASTNodeSearchUtil.getAstNodes(group.getSearchResults(), cu); 1210 for (int i=0; i < nodes.length; i++){ 1211 ASTNode node = nodes[i]; 1212 if (fMethodBinding != null){ 1213 ASTNode n= node; 1215 while (!(n instanceof MethodDeclaration)){ 1216 n = n.getParent(); 1217 } 1218 MethodDeclaration md = (MethodDeclaration)n; 1219 md.accept(fCollector); 1220 } 1221 } 1222 } else { 1223 cu.accept(fCollector); 1224 } 1225 List constraints= Arrays.asList(fCollector.getConstraints()); 1226 fConstraintCache.put(unit, constraints); 1227 return constraints; 1228 } 1229 1230 1233 private String updateImports(CompilationUnit astRoot, MultiTextEdit rootEdit) throws CoreException{ 1234 ImportRewrite rewrite= StubUtility.createImportRewrite(astRoot, true); 1235 String typeName= rewrite.addImport(fSelectedType.getQualifiedName()); 1236 rootEdit.addChild(rewrite.rewriteImports(null)); 1237 return typeName; 1238 } 1239 1240 1243 1246 public Collection getValidTypes() { 1247 return fValidTypes; 1248 } 1249 1250 public ITypeBinding getOriginalType(){ 1251 return fSelectionTypeBinding; 1252 } 1253 1254 private void setOriginalType(ITypeBinding originalType){ 1255 fSelectionTypeBinding= originalType; 1256 fSelectedType= findSuperTypeByName(originalType, fSelectedTypeName); 1257 } 1258 1259 public String getTarget() { 1260 String typeName= fSelectionTypeBinding == null ? "" : fSelectionTypeBinding.getName() + " "; if (fFieldBinding != null) { 1262 return typeName + fFieldBinding.getName(); 1263 } else if (fMethodBinding != null) { 1264 if (fParamIndex == -1) { 1265 return typeName + fMethodBinding.getName() + "(...)"; } else { 1267 return typeName + fParamName; 1268 } 1269 } else if (fSelectionBinding != null) { 1270 return typeName + fSelectionBinding.getName(); 1271 } else { 1272 return typeName; 1273 } 1274 } 1275 1276 1280 public Collection getValidTypeNames() { 1281 Collection typeNames= new ArrayList (); 1282 for (Iterator it= fValidTypes.iterator(); it.hasNext();) { 1283 ITypeBinding type= (ITypeBinding) it.next(); 1284 typeNames.add(type.getQualifiedName()); 1285 } 1286 1287 return typeNames; 1288 } 1289 1290 1298 private ASTNode getTargetNode(ICompilationUnit unit, int offset, int length) { 1299 CompilationUnit root= ASTCreator.createAST(unit, null); 1300 ASTNode node= NodeFinder.perform(root, offset, length); 1301 return node; 1302 } 1303 1304 1309 private ICompilationUnit[] collectAffectedUnits(IProgressMonitor pm) throws CoreException { 1310 1314 pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 100); 1315 1316 if (fAffectedUnits != null) { 1317 if (DEBUG) printCollection("affected units: ", Arrays.asList(fAffectedUnits)); pm.worked(100); 1319 return fAffectedUnits; 1320 } 1321 if (fMethodBinding != null) { 1322 if (fMethodBinding != null) { 1323 1324 1325 IMethod selectedMethod= (IMethod) fMethodBinding.getJavaElement(); 1326 if (selectedMethod == null) { 1327 Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_no_method); 1329 } 1330 1331 1334 IMethod root= selectedMethod; 1335 if (! root.getDeclaringType().isInterface() && MethodChecks.isVirtual(root)) { 1336 final SubProgressMonitor subMonitor= new SubProgressMonitor(pm, 5); 1337 IMethod inInterface= MethodChecks.isDeclaredInInterface(root, root.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(subMonitor, 1)), subMonitor); 1338 if (inInterface != null && !inInterface.equals(root)) 1339 root= inInterface; 1340 } 1341 1342 1344 IMethod[] rippleMethods= RippleMethodFinder2.getRelatedMethods( 1345 root, new SubProgressMonitor(pm, 15), null); 1346 SearchPattern pattern= RefactoringSearchEngine.createOrPattern( 1347 rippleMethods, IJavaSearchConstants.ALL_OCCURRENCES); 1348 1349 IJavaSearchScope scope= RefactoringScopeFactory.create(selectedMethod); 1352 CollectingSearchRequestor csr= new CollectingSearchRequestor(); 1353 1354 SearchResultGroup[] groups= RefactoringSearchEngine.search( 1355 pattern, 1356 null, 1357 scope, 1358 csr, 1359 new SubProgressMonitor(pm, 80), 1360 new RefactoringStatus()); 1362 fAffectedUnits= getCus(groups); 1363 } 1364 } else if (fFieldBinding != null) { 1365 IField iField= (IField) fFieldBinding.getJavaElement(); 1366 if (iField == null) { 1367 Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_no_filed); 1369 } 1370 SearchPattern pattern= SearchPattern.createPattern( 1371 iField, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); 1372 IJavaSearchScope scope= RefactoringScopeFactory.create(iField); 1373 CollectingSearchRequestor csr= new CollectingSearchRequestor(); 1374 SearchResultGroup[] groups= 1375 RefactoringSearchEngine.search(pattern, null, scope, csr, new SubProgressMonitor(pm, 100), 1376 new RefactoringStatus()); fAffectedUnits= getCus(groups); 1378 } else { 1379 fAffectedUnits= new ICompilationUnit[] { fCu }; 1382 } 1383 if (DEBUG) { 1384 System.out.println("Determining affected CUs:"); for (int i= 0; i < fAffectedUnits.length; i++) { 1386 System.out.println(" affected CU: " + fAffectedUnits[i].getElementName()); } 1388 } 1389 pm.done(); 1390 return fAffectedUnits; 1391 } 1392 1393 public void setSelectedType(ITypeBinding type){ 1394 fSelectedType= type; 1395 } 1396 1397 1400 1403 private static boolean isNull(ConstraintVariable cv) { 1404 return cv instanceof ExpressionVariable && ((ExpressionVariable)cv).getExpressionType() == ASTNode.NULL_LITERAL; 1405 } 1406 1407 1408 1411 void printCollection(String title, Collection l) { 1412 System.out.println(l.size() + " " + title); for (Iterator it= l.iterator(); it.hasNext();) { 1414 System.out.println(" " + it.next()); } 1416 } 1417 1418 1421 private ICompilationUnit[] getCus(SearchResultGroup[] groups) { 1422 List result= new ArrayList (groups.length); 1423 for (int i= 0; i < groups.length; i++) { 1424 SearchResultGroup group= groups[i]; 1425 ICompilationUnit cu= group.getCompilationUnit(); 1426 if (cu != null) { 1427 result.add(cu); 1428 fCuToSearchResultGroup.put(cu, group); 1429 } 1430 } 1431 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 1432 } 1433 1434 1438 public Set getAllSuperTypes(ITypeBinding type){ 1439 Set result= new HashSet (); 1440 result.add(type); 1441 if (type.getSuperclass() != null){ 1442 result.addAll(getAllSuperTypes(type.getSuperclass())); 1443 } 1444 ITypeBinding[] interfaces= type.getInterfaces(); 1445 for (int i=0; i < interfaces.length; i++){ 1446 result.addAll(getAllSuperTypes(interfaces[i])); 1447 } 1448 if ((type != fObject) && !contains(result, fObject)){ 1449 result.add(fObject); 1450 } 1451 return result; 1452 } 1453 1454 private ITypeBinding findSuperTypeByName(ITypeBinding type, String superTypeName){ 1455 Set superTypes= getAllSuperTypes(type); 1456 for (Iterator it= superTypes.iterator(); it.hasNext(); ){ 1457 ITypeBinding sup= (ITypeBinding)it.next(); 1458 if (sup.getQualifiedName().equals(superTypeName)){ 1459 return sup; 1460 } 1461 } 1462 return null; 1463 } 1464 1465 public boolean isSubTypeOf(ITypeBinding type1, ITypeBinding type2){ 1466 1467 if (type1.isParameterizedType() && type1.getTypeDeclaration().isEqualTo(type2.getTypeDeclaration())){ 1469 return true; 1470 } 1471 Set superTypes= getAllSuperTypes(type1); 1472 return contains(superTypes, type2); 1473 } 1474 1475 private static boolean contains(Collection c, ITypeBinding binding){ 1476 for (Iterator it=c.iterator(); it.hasNext(); ){ 1477 ITypeBinding b = (ITypeBinding)it.next(); 1478 if (Bindings.equals(b, binding)) return true; 1479 } 1480 return false; 1481 } 1482 1483 1486 public RefactoringStatus initialize(RefactoringArguments arguments) { 1487 if (arguments instanceof JavaRefactoringArguments) { 1488 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 1489 final String selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION); 1490 if (selection != null) { 1491 int offset= -1; 1492 int length= -1; 1493 final StringTokenizer tokenizer= new StringTokenizer (selection); 1494 if (tokenizer.hasMoreTokens()) 1495 offset= Integer.valueOf(tokenizer.nextToken()).intValue(); 1496 if (tokenizer.hasMoreTokens()) 1497 length= Integer.valueOf(tokenizer.nextToken()).intValue(); 1498 if (offset >= 0 && length >= 0) { 1499 fSelectionStart= offset; 1500 fSelectionLength= length; 1501 } else 1502 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object [] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION})); 1503 } else 1504 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION)); 1505 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 1506 if (handle != null) { 1507 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1508 if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT) 1509 return createInputFatalStatus(element, IJavaRefactorings.GENERALIZE_TYPE); 1510 else 1511 fCu= (ICompilationUnit) element; 1512 } else 1513 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 1514 final String type= extended.getAttribute(ATTRIBUTE_TYPE); 1515 if (type != null && !"".equals(type)) fSelectedTypeName= type; 1517 else 1518 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TYPE)); 1519 } else 1520 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 1521 return new RefactoringStatus(); 1522 } 1523} 1524 | Popular Tags |