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.Collections ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.Iterator ; 20 import java.util.LinkedHashSet ; 21 import java.util.LinkedList ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.Set ; 25 26 import org.eclipse.text.edits.MalformedTreeException; 27 import org.eclipse.text.edits.TextEdit; 28 29 import org.eclipse.core.runtime.Assert; 30 import org.eclipse.core.runtime.CoreException; 31 import org.eclipse.core.runtime.IProgressMonitor; 32 import org.eclipse.core.runtime.NullProgressMonitor; 33 import org.eclipse.core.runtime.OperationCanceledException; 34 import org.eclipse.core.runtime.SubProgressMonitor; 35 36 import org.eclipse.jface.text.BadLocationException; 37 import org.eclipse.jface.text.Document; 38 import org.eclipse.jface.text.IDocument; 39 40 import org.eclipse.ltk.core.refactoring.Change; 41 import org.eclipse.ltk.core.refactoring.GroupCategory; 42 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 43 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 44 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 45 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 46 import org.eclipse.ltk.core.refactoring.TextChange; 47 import org.eclipse.ltk.core.refactoring.TextEditBasedChange; 48 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 49 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 50 51 import org.eclipse.jdt.core.Flags; 52 import org.eclipse.jdt.core.ICompilationUnit; 53 import org.eclipse.jdt.core.IField; 54 import org.eclipse.jdt.core.IJavaElement; 55 import org.eclipse.jdt.core.IJavaProject; 56 import org.eclipse.jdt.core.IMember; 57 import org.eclipse.jdt.core.IMethod; 58 import org.eclipse.jdt.core.IType; 59 import org.eclipse.jdt.core.ITypeHierarchy; 60 import org.eclipse.jdt.core.ITypeParameter; 61 import org.eclipse.jdt.core.JavaCore; 62 import org.eclipse.jdt.core.JavaModelException; 63 import org.eclipse.jdt.core.Signature; 64 import org.eclipse.jdt.core.dom.AST; 65 import org.eclipse.jdt.core.dom.ASTNode; 66 import org.eclipse.jdt.core.dom.ASTParser; 67 import org.eclipse.jdt.core.dom.ASTRequestor; 68 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 69 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 70 import org.eclipse.jdt.core.dom.Block; 71 import org.eclipse.jdt.core.dom.BodyDeclaration; 72 import org.eclipse.jdt.core.dom.CompilationUnit; 73 import org.eclipse.jdt.core.dom.Expression; 74 import org.eclipse.jdt.core.dom.FieldAccess; 75 import org.eclipse.jdt.core.dom.FieldDeclaration; 76 import org.eclipse.jdt.core.dom.IBinding; 77 import org.eclipse.jdt.core.dom.IMethodBinding; 78 import org.eclipse.jdt.core.dom.ITypeBinding; 79 import org.eclipse.jdt.core.dom.Javadoc; 80 import org.eclipse.jdt.core.dom.MarkerAnnotation; 81 import org.eclipse.jdt.core.dom.MethodDeclaration; 82 import org.eclipse.jdt.core.dom.MethodInvocation; 83 import org.eclipse.jdt.core.dom.Modifier; 84 import org.eclipse.jdt.core.dom.ReturnStatement; 85 import org.eclipse.jdt.core.dom.SimpleName; 86 import org.eclipse.jdt.core.dom.SuperFieldAccess; 87 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 88 import org.eclipse.jdt.core.dom.ThisExpression; 89 import org.eclipse.jdt.core.dom.TypeDeclarationStatement; 90 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 91 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 92 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition; 93 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 94 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 95 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; 96 97 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 98 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 99 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 100 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 101 import org.eclipse.jdt.internal.corext.dom.Bindings; 102 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; 103 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 104 import org.eclipse.jdt.internal.corext.refactoring.Checks; 105 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 106 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 107 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 108 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 109 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 110 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 111 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 112 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; 113 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 114 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; 115 import org.eclipse.jdt.internal.corext.refactoring.reorg.SourceReferenceUtil; 116 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver; 117 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; 118 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 119 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ISourceConstraintVariable; 120 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable; 121 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; 122 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 123 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 124 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager; 125 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 126 import org.eclipse.jdt.internal.corext.util.JdtFlags; 127 import org.eclipse.jdt.internal.corext.util.Messages; 128 import org.eclipse.jdt.internal.corext.util.Strings; 129 130 import org.eclipse.jdt.ui.CodeGeneration; 131 import org.eclipse.jdt.ui.JavaElementLabels; 132 133 import org.eclipse.jdt.internal.ui.JavaPlugin; 134 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; 135 136 141 public class PullUpRefactoringProcessor extends HierarchyProcessor { 142 143 146 private static class PullUpAstNodeMapper extends TypeVariableMapper { 147 148 149 private boolean fAnonymousClassDeclaration= false; 150 151 152 private final CompilationUnitRewrite fSourceRewriter; 153 154 155 private final IType fSuperReferenceType; 156 157 158 private final CompilationUnitRewrite fTargetRewriter; 159 160 161 private boolean fTypeDeclarationStatement= false; 162 163 164 private final IMethodBinding fEnclosingMethod; 165 166 181 public PullUpAstNodeMapper(final CompilationUnitRewrite sourceRewriter, final CompilationUnitRewrite targetRewriter, final ASTRewrite rewrite, final IType type, final TypeVariableMaplet[] mapping, final IMethodBinding enclosing) { 182 super(rewrite, mapping); 183 Assert.isNotNull(rewrite); 184 Assert.isNotNull(type); 185 fSourceRewriter= sourceRewriter; 186 fTargetRewriter= targetRewriter; 187 fSuperReferenceType= type; 188 fEnclosingMethod= enclosing; 189 } 190 191 public final void endVisit(final AnonymousClassDeclaration node) { 192 fAnonymousClassDeclaration= false; 193 super.endVisit(node); 194 } 195 196 public final void endVisit(final TypeDeclarationStatement node) { 197 fTypeDeclarationStatement= false; 198 super.endVisit(node); 199 } 200 201 public final boolean visit(final AnonymousClassDeclaration node) { 202 fAnonymousClassDeclaration= true; 203 return super.visit(node); 204 } 205 206 public final boolean visit(final SuperFieldAccess node) { 207 if (!fAnonymousClassDeclaration && !fTypeDeclarationStatement) { 208 final AST ast= node.getAST(); 209 final FieldAccess access= ast.newFieldAccess(); 210 access.setExpression(ast.newThisExpression()); 211 access.setName(ast.newSimpleName(node.getName().getIdentifier())); 212 fRewrite.replace(node, access, null); 213 if (!fSourceRewriter.getCu().equals(fTargetRewriter.getCu())) 214 fSourceRewriter.getImportRemover().registerRemovedNode(node); 215 return true; 216 } 217 return false; 218 } 219 220 public final boolean visit(final SuperMethodInvocation node) { 221 if (!fAnonymousClassDeclaration && !fTypeDeclarationStatement) { 222 final IBinding superBinding= node.getName().resolveBinding(); 223 if (superBinding instanceof IMethodBinding) { 224 final IMethodBinding extended= (IMethodBinding) superBinding; 225 if (fEnclosingMethod != null && fEnclosingMethod.overrides(extended)) 226 return true; 227 final ITypeBinding declaringBinding= extended.getDeclaringClass(); 228 if (declaringBinding != null) { 229 final IType type= (IType) declaringBinding.getJavaElement(); 230 if (!fSuperReferenceType.equals(type)) 231 return true; 232 } 233 } 234 final AST ast= node.getAST(); 235 final ThisExpression expression= ast.newThisExpression(); 236 final MethodInvocation invocation= ast.newMethodInvocation(); 237 final SimpleName simple= ast.newSimpleName(node.getName().getIdentifier()); 238 invocation.setName(simple); 239 invocation.setExpression(expression); 240 final List arguments= (List ) node.getStructuralProperty(SuperMethodInvocation.ARGUMENTS_PROPERTY); 241 if (arguments != null && arguments.size() > 0) { 242 final ListRewrite rewriter= fRewrite.getListRewrite(invocation, MethodInvocation.ARGUMENTS_PROPERTY); 243 rewriter.insertLast(rewriter.createCopyTarget((ASTNode) arguments.get(0), (ASTNode) arguments.get(arguments.size() - 1)), null); 244 } 245 fRewrite.replace(node, invocation, null); 246 if (!fSourceRewriter.getCu().equals(fTargetRewriter.getCu())) 247 fSourceRewriter.getImportRemover().registerRemovedNode(node); 248 return true; 249 } 250 return false; 251 } 252 253 public final boolean visit(final TypeDeclarationStatement node) { 254 fTypeDeclarationStatement= true; 255 return super.visit(node); 256 } 257 } 258 259 protected static final String ATTRIBUTE_ABSTRACT= "abstract"; 261 protected static final String ATTRIBUTE_DELETE= "delete"; 263 protected static final String ATTRIBUTE_PULL= "pull"; 265 protected static final String ATTRIBUTE_STUBS= "stubs"; 267 private static final String IDENTIFIER= "org.eclipse.jdt.ui.pullUpProcessor"; 269 270 private static final GroupCategorySet SET_PULL_UP= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.pullUp", RefactoringCoreMessages.PullUpRefactoring_category_name, RefactoringCoreMessages.PullUpRefactoring_category_description)); 272 273 private static void addMatchingMember(final Map mapping, final IMember key, final IMember matchingMember) { 274 Set matchingSet; 275 if (mapping.containsKey(key)) { 276 matchingSet= (Set ) mapping.get(key); 277 } else { 278 matchingSet= new HashSet (); 279 mapping.put(key, matchingSet); 280 } 281 Assert.isTrue(!matchingSet.contains(matchingMember)); 282 matchingSet.add(matchingMember); 283 } 284 285 private static Block createMethodStub(final MethodDeclaration method, final AST ast) { 286 final Block body= ast.newBlock(); 287 final Expression expression= ASTNodeFactory.newDefaultExpression(ast, method.getReturnType2(), method.getExtraDimensions()); 288 if (expression != null) { 289 final ReturnStatement returnStatement= ast.newReturnStatement(); 290 returnStatement.setExpression(expression); 291 body.statements().add(returnStatement); 292 } 293 return body; 294 } 295 296 private static Set getEffectedSubTypes(final ITypeHierarchy hierarchy, final IType type) throws JavaModelException { 297 IType[] types= null; 298 final boolean isInterface= type.isInterface(); 299 if (isInterface) { 300 final Collection remove= new ArrayList (); 301 final List list= new ArrayList (Arrays.asList(hierarchy.getSubtypes(type))); 302 for (final Iterator iterator= list.iterator(); iterator.hasNext();) { 303 final IType element= (IType) iterator.next(); 304 if (element.isInterface()) 305 remove.add(element); 306 } 307 list.removeAll(remove); 308 types= (IType[]) list.toArray(new IType[list.size()]); 309 } else 310 types= hierarchy.getSubclasses(type); 311 final Set result= new HashSet (); 312 for (int index= 0; index < types.length; index++) { 313 if (!isInterface && JdtFlags.isAbstract(types[index])) 314 result.addAll(getEffectedSubTypes(hierarchy, types[index])); 315 else 316 result.add(types[index]); 317 } 318 return result; 319 } 320 321 private static IMember[] getMembers(final IMember[] members, final int type) { 322 final List list= Arrays.asList(JavaElementUtil.getElementsOfType(members, type)); 323 return (IMember[]) list.toArray(new IMember[list.size()]); 324 } 325 326 private static void mergeMaps(final Map result, final Map map) { 327 for (final Iterator iter= result.keySet().iterator(); iter.hasNext();) { 328 final IMember key= (IMember) iter.next(); 329 if (map.containsKey(key)) { 330 final Set resultSet= (Set ) result.get(key); 331 final Set mapSet= (Set ) map.get(key); 332 resultSet.addAll(mapSet); 333 } 334 } 335 } 336 337 private static void upgradeMap(final Map result, final Map map) { 338 for (final Iterator iter= map.keySet().iterator(); iter.hasNext();) { 339 final IMember key= (IMember) iter.next(); 340 if (!result.containsKey(key)) { 341 final Set mapSet= (Set ) map.get(key); 342 final Set resultSet= new HashSet (mapSet); 343 result.put(key, resultSet); 344 } 345 } 346 } 347 348 349 protected IMethod[] fAbstractMethods= new IMethod[0]; 350 351 352 private ITypeHierarchy fCachedDeclaringSuperTypeHierarchy; 353 354 355 private ITypeHierarchy fCachedDestinationTypeHierarchy; 356 357 358 private Set fCachedSkippedSuperTypes; 359 360 361 protected Map fCompilationUnitRewrites; 362 363 364 protected boolean fCreateMethodStubs= true; 365 366 367 protected IMethod[] fDeletedMethods= new IMethod[0]; 368 369 370 protected IType fDestinationType; 371 372 382 public PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings) { 383 this(members, settings, false); 384 } 385 386 399 protected PullUpRefactoringProcessor(final IMember[] members, final CodeGenerationSettings settings, final boolean layer) { 400 super(members, settings, layer); 401 if (members != null) { 402 final IType type= RefactoringAvailabilityTester.getTopLevelType(fMembersToMove); 403 try { 404 if (type != null && RefactoringAvailabilityTester.getPullUpMembers(type).length != 0) { 405 fCachedDeclaringType= RefactoringAvailabilityTester.getTopLevelType(fMembersToMove); 406 fMembersToMove= new IMember[0]; 407 } 408 } catch (JavaModelException exception) { 409 JavaPlugin.log(exception); 410 } 411 } 412 } 413 414 private void addAllRequiredPullableMembers(final List queue, final IMember member, final IProgressMonitor monitor) throws JavaModelException { 415 Assert.isNotNull(queue); 416 Assert.isNotNull(member); 417 Assert.isNotNull(monitor); 418 SubProgressMonitor sub= null; 419 try { 420 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, 3); 421 final IMethod[] requiredMethods= ReferenceFinderUtil.getMethodsReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1)); 422 sub= new SubProgressMonitor(monitor, 1); 423 boolean isStatic= false; 424 try { 425 sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredMethods.length); 426 isStatic= JdtFlags.isStatic(member); 427 for (int index= 0; index < requiredMethods.length; index++) { 428 final IMethod requiredMethod= requiredMethods[index]; 429 if (isStatic && !JdtFlags.isStatic(requiredMethod)) 430 continue; 431 if (isRequiredPullableMember(queue, requiredMethod) && !(MethodChecks.isVirtual(requiredMethod) && isAvailableInDestination(requiredMethod, new SubProgressMonitor(sub, 1)))) 432 queue.add(requiredMethod); 433 } 434 } finally { 435 sub.done(); 436 } 437 final IField[] requiredFields= ReferenceFinderUtil.getFieldsReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1)); 438 sub= new SubProgressMonitor(monitor, 1); 439 try { 440 sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredFields.length); 441 isStatic= JdtFlags.isStatic(member); 442 for (int index= 0; index < requiredFields.length; index++) { 443 final IField requiredField= requiredFields[index]; 444 if (isStatic && !JdtFlags.isStatic(requiredField)) 445 continue; 446 if (isRequiredPullableMember(queue, requiredField)) 447 queue.add(requiredField); 448 } 449 } finally { 450 sub.done(); 451 } 452 final IType[] requiredTypes= ReferenceFinderUtil.getTypesReferencedIn(new IJavaElement[] { member}, fOwner, new SubProgressMonitor(monitor, 1)); 453 sub= new SubProgressMonitor(monitor, 1); 454 try { 455 sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, requiredMethods.length); 456 isStatic= JdtFlags.isStatic(member); 457 for (int index= 0; index < requiredTypes.length; index++) { 458 final IType requiredType= requiredTypes[index]; 459 if (isStatic && !JdtFlags.isStatic(requiredType)) 460 continue; 461 if (isRequiredPullableMember(queue, requiredType)) 462 queue.add(requiredType); 463 } 464 } finally { 465 sub.done(); 466 } 467 } finally { 468 monitor.done(); 469 } 470 } 471 472 private void addMethodStubForAbstractMethod(final IMethod sourceMethod, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration typeToCreateStubIn, final ICompilationUnit newCu, final CompilationUnitRewrite rewriter, final Map adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException { 473 final MethodDeclaration methodToCreateStubFor= ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, declaringCuNode); 474 final AST ast= rewriter.getRoot().getAST(); 475 final MethodDeclaration newMethod= ast.newMethodDeclaration(); 476 newMethod.setBody(createMethodStub(methodToCreateStubFor, ast)); 477 newMethod.setConstructor(false); 478 newMethod.setExtraDimensions(methodToCreateStubFor.getExtraDimensions()); 479 newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getModifiersWithUpdatedVisibility(sourceMethod, JdtFlags.clearFlag(Modifier.NATIVE | Modifier.ABSTRACT, methodToCreateStubFor.getModifiers()), adjustments, new SubProgressMonitor(monitor, 1), false, status))); 480 newMethod.setName(((SimpleName) ASTNode.copySubtree(ast, methodToCreateStubFor.getName()))); 481 final TypeVariableMaplet[] mapping= TypeVariableUtil.composeMappings(TypeVariableUtil.subTypeToSuperType(getDeclaringType(), getDestinationType()), TypeVariableUtil.superTypeToInheritedType(getDestinationType(), ((IType) typeToCreateStubIn.resolveBinding().getJavaElement()))); 482 copyReturnType(rewriter.getASTRewrite(), getDeclaringType().getCompilationUnit(), methodToCreateStubFor, newMethod, mapping); 483 copyParameters(rewriter.getASTRewrite(), getDeclaringType().getCompilationUnit(), methodToCreateStubFor, newMethod, mapping); 484 copyThrownExceptions(methodToCreateStubFor, newMethod); 485 newMethod.setJavadoc(createJavadocForStub(typeToCreateStubIn.getName().getIdentifier(), methodToCreateStubFor, newMethod, newCu, rewriter.getASTRewrite())); 486 ImportRewriteUtil.addImports(rewriter, newMethod, new HashMap (), new HashMap (), false); 487 rewriter.getASTRewrite().getListRewrite(typeToCreateStubIn, typeToCreateStubIn.getBodyDeclarationsProperty()).insertAt(newMethod, ASTNodes.getInsertionIndex(newMethod, typeToCreateStubIn.bodyDeclarations()), rewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_method_stub, SET_PULL_UP)); 488 } 489 490 private void addNecessaryMethodStubs(final List effected, final CompilationUnit root, final CompilationUnitRewrite unitRewriter, final Map adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException { 491 final IType declaringType= getDeclaringType(); 492 final IMethod[] methods= getAbstractMethods(); 493 try { 494 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, effected.size()); 495 for (final Iterator iter= effected.iterator(); iter.hasNext();) { 496 final IType type= (IType) iter.next(); 497 if (type.equals(declaringType)) 498 continue; 499 final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, unitRewriter.getRoot()); 500 final ICompilationUnit unit= type.getCompilationUnit(); 501 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1); 502 try { 503 subMonitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, methods.length); 504 for (int j= 0; j < methods.length; j++) { 505 final IMethod method= methods[j]; 506 if (null == JavaModelUtil.findMethod(method.getElementName(), method.getParameterTypes(), method.isConstructor(), type)) { 507 addMethodStubForAbstractMethod(method, root, declaration, unit, unitRewriter, adjustments, new SubProgressMonitor(subMonitor, 1), status); 508 } 509 } 510 subMonitor.done(); 511 } finally { 512 subMonitor.done(); 513 } 514 } 515 } finally { 516 monitor.done(); 517 } 518 } 519 520 protected boolean canBeAccessedFrom(final IMember member, final IType target, final ITypeHierarchy hierarchy) throws JavaModelException { 521 if (super.canBeAccessedFrom(member, target, hierarchy)) { 522 if (target.isInterface()) 523 return true; 524 if (target.equals(member.getDeclaringType())) 525 return true; 526 if (target.equals(member)) 527 return true; 528 if (member instanceof IMethod) { 529 final IMethod method= (IMethod) member; 530 final IMethod stub= target.getMethod(method.getElementName(), method.getParameterTypes()); 531 if (stub.exists()) 532 return true; 533 } 534 if (member.getDeclaringType() == null) { 535 if (!(member instanceof IType)) 536 return false; 537 if (JdtFlags.isPublic(member)) 538 return true; 539 if (!JdtFlags.isPackageVisible(member)) 540 return false; 541 if (JavaModelUtil.isSamePackage(((IType) member).getPackageFragment(), target.getPackageFragment())) 542 return true; 543 final IType type= member.getDeclaringType(); 544 if (type != null) 545 return hierarchy.contains(type); 546 return false; 547 } 548 final IType declaringType= member.getDeclaringType(); 549 if (!canBeAccessedFrom(declaringType, target, hierarchy)) 550 return false; 551 if (declaringType.equals(getDeclaringType())) 552 return false; 553 return true; 554 } 555 return false; 556 } 557 558 private RefactoringStatus checkAccessedFields(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException { 559 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 2); 560 final RefactoringStatus result= new RefactoringStatus(); 561 562 final List pulledUpList= Arrays.asList(fMembersToMove); 563 final List deletedList= Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1))); 564 final IField[] accessedFields= ReferenceFinderUtil.getFieldsReferencedIn(fMembersToMove, fOwner, new SubProgressMonitor(monitor, 1)); 565 566 final IType destination= getDestinationType(); 567 for (int i= 0; i < accessedFields.length; i++) { 568 final IField field= accessedFields[i]; 569 if (!field.exists()) 570 continue; 571 572 boolean isAccessible= pulledUpList.contains(field) || deletedList.contains(field) || canBeAccessedFrom(field, destination, hierarchy) || Flags.isEnum(field.getFlags()); 573 if (!isAccessible) { 574 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_field_not_accessible, new String [] { JavaElementLabels.getTextLabel(field, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 575 result.addError(message, JavaStatusContext.create(field)); 576 } else if (getSkippedSuperTypes(new SubProgressMonitor(monitor, 1)).contains(field.getDeclaringType())) { 577 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_field_cannot_be_accessed, new String [] { JavaElementLabels.getTextLabel(field, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 578 result.addError(message, JavaStatusContext.create(field)); 579 } 580 } 581 monitor.done(); 582 return result; 583 } 584 585 private RefactoringStatus checkAccessedMethods(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException { 586 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 2); 587 final RefactoringStatus result= new RefactoringStatus(); 588 589 final List pulledUpList= Arrays.asList(fMembersToMove); 590 final List declaredAbstractList= Arrays.asList(fAbstractMethods); 591 final List deletedList= Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1))); 592 final IMethod[] accessedMethods= ReferenceFinderUtil.getMethodsReferencedIn(fMembersToMove, fOwner, new SubProgressMonitor(monitor, 1)); 593 594 final IType destination= getDestinationType(); 595 for (int index= 0; index < accessedMethods.length; index++) { 596 final IMethod method= accessedMethods[index]; 597 if (!method.exists()) 598 continue; 599 boolean isAccessible= pulledUpList.contains(method) || deletedList.contains(method) || declaredAbstractList.contains(method) || canBeAccessedFrom(method, destination, hierarchy); 600 if (!isAccessible) { 601 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_method_not_accessible, new String [] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 602 result.addError(message, JavaStatusContext.create(method)); 603 } else if (getSkippedSuperTypes(new SubProgressMonitor(monitor, 1)).contains(method.getDeclaringType())) { 604 final String [] keys= { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)}; 605 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_method_cannot_be_accessed, keys); 606 result.addError(message, JavaStatusContext.create(method)); 607 } 608 } 609 monitor.done(); 610 return result; 611 } 612 613 private RefactoringStatus checkAccessedTypes(final IProgressMonitor monitor, final ITypeHierarchy hierarchy) throws JavaModelException { 614 final RefactoringStatus result= new RefactoringStatus(); 615 final IType[] accessedTypes= getTypesReferencedInMovedMembers(monitor); 616 final IType destination= getDestinationType(); 617 final List pulledUpList= Arrays.asList(fMembersToMove); 618 for (int index= 0; index < accessedTypes.length; index++) { 619 final IType type= accessedTypes[index]; 620 if (!type.exists()) 621 continue; 622 623 if (!canBeAccessedFrom(type, destination, hierarchy) && !pulledUpList.contains(type)) { 624 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_type_not_accessible, new String [] { JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 625 result.addError(message, JavaStatusContext.create(type)); 626 } 627 } 628 monitor.done(); 629 return result; 630 } 631 632 private RefactoringStatus checkAccesses(final IProgressMonitor monitor) throws JavaModelException { 633 final RefactoringStatus result= new RefactoringStatus(); 634 try { 635 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking_referenced_elements, 4); 636 final ITypeHierarchy hierarchy= getDestinationType().newSupertypeHierarchy(fOwner, new SubProgressMonitor(monitor, 1)); 637 result.merge(checkAccessedTypes(new SubProgressMonitor(monitor, 1), hierarchy)); 638 result.merge(checkAccessedFields(new SubProgressMonitor(monitor, 1), hierarchy)); 639 result.merge(checkAccessedMethods(new SubProgressMonitor(monitor, 1), hierarchy)); 640 } finally { 641 monitor.done(); 642 } 643 return result; 644 } 645 646 private void checkAccessModifiers(final RefactoringStatus result, final Set notDeletedMembersInSubtypes) throws JavaModelException { 647 if (fDestinationType.isInterface()) 648 return; 649 final List toDeclareAbstract= Arrays.asList(fAbstractMethods); 650 for (final Iterator iter= notDeletedMembersInSubtypes.iterator(); iter.hasNext();) { 651 final IMember member= (IMember) iter.next(); 652 if (member.getElementType() == IJavaElement.METHOD && !toDeclareAbstract.contains(member)) { 653 final IMethod method= ((IMethod) member); 654 if (method.getDeclaringType().getPackageFragment().equals(fDestinationType.getPackageFragment())) { 655 if (JdtFlags.isPrivate(method)) 656 result.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_lower_default_visibility, new String [] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(method.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(method)); 657 } else if (!JdtFlags.isPublic(method) && !JdtFlags.isProtected(method)) 658 result.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_lower_protected_visibility, new String [] { JavaElementLabels.getTextLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(method.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(method)); 659 } 660 } 661 } 662 663 protected RefactoringStatus checkDeclaringSuperTypes(final IProgressMonitor monitor) throws JavaModelException { 664 final RefactoringStatus result= new RefactoringStatus(); 665 if (getCandidateTypes(result, monitor).length == 0 && !result.hasFatalError()) { 666 final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_not_this_type, new String [] { JavaElementLabels.getTextLabel(getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}); 667 return RefactoringStatus.createFatalErrorStatus(msg); 668 } 669 return result; 670 } 671 672 protected RefactoringStatus checkDeclaringType(final IProgressMonitor monitor) throws JavaModelException { 673 final RefactoringStatus status= super.checkDeclaringType(monitor); 674 if (JavaModelUtil.getFullyQualifiedName(getDeclaringType()).equals("java.lang.Object")) status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PullUpRefactoring_no_java_lang_Object)); 676 status.merge(checkDeclaringSuperTypes(monitor)); 677 return status; 678 } 679 680 private void checkFieldTypes(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException { 681 final Map mapping= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), true); 682 for (int i= 0; i < fMembersToMove.length; i++) { 683 if (fMembersToMove[i].getElementType() != IJavaElement.FIELD) 684 continue; 685 final IField field= (IField) fMembersToMove[i]; 686 final String type= Signature.toString(field.getTypeSignature()); 687 Assert.isTrue(mapping.containsKey(field)); 688 for (final Iterator iter= ((Set ) mapping.get(field)).iterator(); iter.hasNext();) { 689 final IField matchingField= (IField) iter.next(); 690 if (field.equals(matchingField)) 691 continue; 692 if (type.equals(Signature.toString(matchingField.getTypeSignature()))) 693 continue; 694 final String [] keys= { JavaElementLabels.getTextLabel(matchingField, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(matchingField.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}; 695 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_different_field_type, keys); 696 final RefactoringStatusContext context= JavaStatusContext.create(matchingField.getCompilationUnit(), matchingField.getSourceRange()); 697 status.addError(message, context); 698 } 699 } 700 } 701 702 705 public RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException { 706 try { 707 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 12); 708 clearCaches(); 709 710 final RefactoringStatus result= new RefactoringStatus(); 711 result.merge(createWorkingCopyLayer(new SubProgressMonitor(monitor, 4))); 712 if (result.hasFatalError()) 713 return result; 714 if (monitor.isCanceled()) 715 throw new OperationCanceledException(); 716 result.merge(checkGenericDeclaringType(new SubProgressMonitor(monitor, 1))); 717 result.merge(checkFinalFields(new SubProgressMonitor(monitor, 1))); 718 if (monitor.isCanceled()) 719 throw new OperationCanceledException(); 720 result.merge(checkAccesses(new SubProgressMonitor(monitor, 1))); 721 result.merge(checkMembersInTypeAndAllSubtypes(new SubProgressMonitor(monitor, 2))); 722 result.merge(checkIfSkippingOverElements(new SubProgressMonitor(monitor, 1))); 723 if (monitor.isCanceled()) 724 throw new OperationCanceledException(); 725 if (!JdtFlags.isAbstract(getDestinationType()) && getAbstractMethods().length > 0) 726 result.merge(checkConstructorCalls(getDestinationType(), new SubProgressMonitor(monitor, 1))); 727 else 728 monitor.worked(1); 729 if (result.hasFatalError()) 730 return result; 731 fCompilationUnitRewrites= new HashMap (3); 732 result.merge(checkProjectCompliance(getCompilationUnitRewrite(fCompilationUnitRewrites, getDeclaringType().getCompilationUnit()), getDestinationType(), fMembersToMove)); 733 fChangeManager= createChangeManager(new SubProgressMonitor(monitor, 1), result); 734 result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getRefactoring().getValidationContext())); 735 return result; 736 } finally { 737 monitor.done(); 738 } 739 } 740 741 private RefactoringStatus checkFinalFields(final IProgressMonitor monitor) throws JavaModelException { 742 final RefactoringStatus result= new RefactoringStatus(); 743 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fMembersToMove.length); 744 for (int index= 0; index < fMembersToMove.length; index++) { 745 final IMember member= fMembersToMove[index]; 746 if (member.getElementType() == IJavaElement.FIELD) { 747 if (!JdtFlags.isStatic(member)) { 748 if (JdtFlags.isFinal(member)) { 749 final RefactoringStatusContext context= JavaStatusContext.create(member); 750 result.addWarning(RefactoringCoreMessages.PullUpRefactoring_final_fields, context); 751 } else if (getDestinationType().isInterface()) { 752 final RefactoringStatusContext context= JavaStatusContext.create(member); 753 result.addWarning(RefactoringCoreMessages.PullUpRefactoring_non_final_pull_up_to_interface, context); 754 } 755 } 756 } 757 monitor.worked(1); 758 if (monitor.isCanceled()) 759 throw new OperationCanceledException(); 760 } 761 monitor.done(); 762 return result; 763 } 764 765 private RefactoringStatus checkGenericDeclaringType(final SubProgressMonitor monitor) throws JavaModelException { 766 Assert.isNotNull(monitor); 767 768 final RefactoringStatus status= new RefactoringStatus(); 769 try { 770 final IMember[] pullables= getMembersToMove(); 771 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, pullables.length); 772 773 final IType declaring= getDeclaringType(); 774 final ITypeParameter[] parameters= declaring.getTypeParameters(); 775 if (parameters.length > 0) { 776 final TypeVariableMaplet[] mapping= TypeVariableUtil.subTypeToInheritedType(declaring); 777 IMember member= null; 778 int length= 0; 779 for (int index= 0; index < pullables.length; index++) { 780 member= pullables[index]; 781 final String [] unmapped= TypeVariableUtil.getUnmappedVariables(mapping, declaring, member); 782 length= unmapped.length; 783 switch (length) { 784 case 0: 785 break; 786 case 1: 787 status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable_not_available, new String [] { unmapped[0], declaring.getSuperclassName()}), JavaStatusContext.create(member)); 788 break; 789 case 2: 790 status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable2_not_available, new String [] { unmapped[0], unmapped[1], declaring.getSuperclassName()}), JavaStatusContext.create(member)); 791 break; 792 case 3: 793 status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variable3_not_available, new String [] { unmapped[0], unmapped[1], unmapped[2], declaring.getSuperclassName()}), JavaStatusContext.create(member)); 794 break; 795 default: 796 status.addError(Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_variables_not_available, new String [] { declaring.getSuperclassName()}), JavaStatusContext.create(member)); 797 } 798 monitor.worked(1); 799 if (monitor.isCanceled()) 800 throw new OperationCanceledException(); 801 } 802 } 803 } finally { 804 monitor.done(); 805 } 806 return status; 807 } 808 809 private RefactoringStatus checkIfDeclaredIn(final IMember element, final IType type) throws JavaModelException { 810 if (element instanceof IMethod) 811 return checkIfMethodDeclaredIn((IMethod) element, type); 812 else if (element instanceof IField) 813 return checkIfFieldDeclaredIn((IField) element, type); 814 else if (element instanceof IType) 815 return checkIfTypeDeclaredIn((IType) element, type); 816 Assert.isTrue(false); 817 return null; 818 } 819 820 private RefactoringStatus checkIfFieldDeclaredIn(final IField iField, final IType type) { 821 final IField fieldInType= type.getField(iField.getElementName()); 822 if (!fieldInType.exists()) 823 return null; 824 final String [] keys= { JavaElementLabels.getTextLabel(fieldInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)}; 825 final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Field_declared_in_class, keys); 826 final RefactoringStatusContext context= JavaStatusContext.create(fieldInType); 827 return RefactoringStatus.createWarningStatus(msg, context); 828 } 829 830 private RefactoringStatus checkIfMethodDeclaredIn(final IMethod iMethod, final IType type) throws JavaModelException { 831 final IMethod methodInType= JavaModelUtil.findMethod(iMethod.getElementName(), iMethod.getParameterTypes(), iMethod.isConstructor(), type); 832 if (methodInType == null || !methodInType.exists()) 833 return null; 834 final String [] keys= { JavaElementLabels.getTextLabel(methodInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)}; 835 final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Method_declared_in_class, keys); 836 final RefactoringStatusContext context= JavaStatusContext.create(methodInType); 837 return RefactoringStatus.createWarningStatus(msg, context); 838 } 839 840 private RefactoringStatus checkIfSkippingOverElements(final IProgressMonitor monitor) throws JavaModelException { 841 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1); 842 try { 843 final Set skippedTypes= getSkippedSuperTypes(new SubProgressMonitor(monitor, 1)); 844 final IType[] skipped= (IType[]) skippedTypes.toArray(new IType[skippedTypes.size()]); 845 final RefactoringStatus result= new RefactoringStatus(); 846 for (int i= 0; i < fMembersToMove.length; i++) { 847 final IMember element= fMembersToMove[i]; 848 for (int j= 0; j < skipped.length; j++) { 849 result.merge(checkIfDeclaredIn(element, skipped[j])); 850 } 851 } 852 return result; 853 } finally { 854 monitor.done(); 855 } 856 } 857 858 private RefactoringStatus checkIfTypeDeclaredIn(final IType iType, final IType type) { 859 final IType typeInType= type.getType(iType.getElementName()); 860 if (!typeInType.exists()) 861 return null; 862 final String [] keys= { JavaElementLabels.getTextLabel(typeInType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)}; 863 final String msg= Messages.format(RefactoringCoreMessages.PullUpRefactoring_Type_declared_in_class, keys); 864 final RefactoringStatusContext context= JavaStatusContext.create(typeInType); 865 return RefactoringStatus.createWarningStatus(msg, context); 866 } 867 868 871 public RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 872 try { 873 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1); 874 final RefactoringStatus status= new RefactoringStatus(); 875 status.merge(checkDeclaringType(new SubProgressMonitor(monitor, 1))); 876 if (status.hasFatalError()) 877 return status; 878 status.merge(checkIfMembersExist()); 879 if (status.hasFatalError()) 880 return status; 881 return status; 882 } finally { 883 monitor.done(); 884 } 885 } 886 887 private void checkMembersInDestinationType(final RefactoringStatus status, final Set set) throws JavaModelException { 888 final IMember[] destinationMembers= getCreatedDestinationMembers(); 889 final List list= new ArrayList (destinationMembers.length); 890 list.addAll(Arrays.asList(destinationMembers)); 891 list.addAll(set); 892 list.removeAll(Arrays.asList(fDeletedMethods)); 893 final IMember[] members= (IMember[]) list.toArray(new IMember[list.size()]); 894 status.merge(MemberCheckUtil.checkMembersInDestinationType(members, getDestinationType())); 895 } 896 897 private RefactoringStatus checkMembersInTypeAndAllSubtypes(final IProgressMonitor monitor) throws JavaModelException { 898 final RefactoringStatus result= new RefactoringStatus(); 899 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 3); 900 final Set notDeletedMembers= getNotDeletedMembers(new SubProgressMonitor(monitor, 1)); 901 final Set notDeletedMembersInTargetType= new HashSet (); 902 final Set notDeletedMembersInSubtypes= new HashSet (); 903 for (final Iterator iter= notDeletedMembers.iterator(); iter.hasNext();) { 904 final IMember member= (IMember) iter.next(); 905 if (getDestinationType().equals(member.getDeclaringType())) 906 notDeletedMembersInTargetType.add(member); 907 else 908 notDeletedMembersInSubtypes.add(member); 909 } 910 checkMembersInDestinationType(result, notDeletedMembersInTargetType); 911 checkAccessModifiers(result, notDeletedMembersInSubtypes); 912 checkMethodReturnTypes(new SubProgressMonitor(monitor, 1), result, notDeletedMembersInSubtypes); 913 checkFieldTypes(new SubProgressMonitor(monitor, 1), result); 914 monitor.done(); 915 return result; 916 } 917 918 private void checkMethodReturnTypes(final IProgressMonitor monitor, final RefactoringStatus status, final Set notDeletedMembersInSubtypes) throws JavaModelException { 919 final Map mapping= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), true); 920 final IMember[] members= getCreatedDestinationMembers(); 921 for (int i= 0; i < members.length; i++) { 922 if (members[i].getElementType() != IJavaElement.METHOD) 923 continue; 924 final IMethod method= (IMethod) members[i]; 925 if (mapping.containsKey(method)) { 926 final Set set= (Set ) mapping.get(method); 927 if (set != null) { 928 final String returnType= Signature.toString(Signature.getReturnType(method.getSignature()).toString()); 929 for (final Iterator iter= set.iterator(); iter.hasNext();) { 930 final IMethod matchingMethod= (IMethod) iter.next(); 931 if (method.equals(matchingMethod)) 932 continue; 933 if (!notDeletedMembersInSubtypes.contains(matchingMethod)) 934 continue; 935 if (returnType.equals(Signature.toString(Signature.getReturnType(matchingMethod.getSignature()).toString()))) 936 continue; 937 final String [] keys= { JavaElementLabels.getTextLabel(matchingMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(matchingMethod.getDeclaringType(), JavaElementLabels.ALL_FULLY_QUALIFIED)}; 938 final String message= Messages.format(RefactoringCoreMessages.PullUpRefactoring_different_method_return_type, keys); 939 final RefactoringStatusContext context= JavaStatusContext.create(matchingMethod.getCompilationUnit(), matchingMethod.getNameRange()); 940 status.addError(message, context); 941 } 942 } 943 } 944 } 945 } 946 947 protected void clearCaches() { 948 super.clearCaches(); 949 fCachedMembersReferences.clear(); 950 fCachedDestinationTypeHierarchy= null; 951 fCachedDeclaringSuperTypeHierarchy= null; 952 } 953 954 private void copyBodyOfPulledUpMethod(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod method, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping, final IProgressMonitor monitor) throws JavaModelException { 955 final Block body= oldMethod.getBody(); 956 if (body == null) { 957 newMethod.setBody(null); 958 return; 959 } 960 try { 961 final IDocument document= new Document(method.getCompilationUnit().getBuffer().getContents()); 962 final ASTRewrite rewrite= ASTRewrite.create(body.getAST()); 963 final ITrackedNodePosition position= rewrite.track(body); 964 body.accept(new PullUpAstNodeMapper(sourceRewrite, targetRewrite, rewrite, getDeclaringSuperTypeHierarchy(monitor).getSuperclass(getDeclaringType()), mapping, oldMethod.resolveBinding())); 965 rewrite.rewriteAST(document, method.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 966 String content= document.get(position.getStartPosition(), position.getLength()); 967 final String [] lines= Strings.convertIntoLines(content); 968 Strings.trimIndentation(lines, method.getJavaProject(), false); 969 content= Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(method)); 970 newMethod.setBody((Block) targetRewrite.getASTRewrite().createStringPlaceholder(content, ASTNode.BLOCK)); 971 } catch (MalformedTreeException exception) { 972 JavaPlugin.log(exception); 973 } catch (BadLocationException exception) { 974 JavaPlugin.log(exception); 975 } 976 } 977 978 private void createAbstractMethod(final IMethod sourceMethod, final CompilationUnitRewrite sourceRewriter, final CompilationUnit declaringCuNode, final AbstractTypeDeclaration destination, final TypeVariableMaplet[] mapping, final CompilationUnitRewrite targetRewrite, final Map adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException { 979 final MethodDeclaration oldMethod= ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, declaringCuNode); 980 if (JavaModelUtil.is50OrHigher(sourceMethod.getJavaProject()) && (fSettings.overrideAnnotation || JavaCore.ERROR.equals(sourceMethod.getJavaProject().getOption(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION, true)))) { 981 final MarkerAnnotation annotation= sourceRewriter.getAST().newMarkerAnnotation(); 982 annotation.setTypeName(sourceRewriter.getAST().newSimpleName("Override")); sourceRewriter.getASTRewrite().getListRewrite(oldMethod, MethodDeclaration.MODIFIERS2_PROPERTY).insertFirst(annotation, sourceRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_override_annotation, SET_PULL_UP)); 984 } 985 final MethodDeclaration newMethod= targetRewrite.getAST().newMethodDeclaration(); 986 newMethod.setBody(null); 987 newMethod.setConstructor(false); 988 newMethod.setExtraDimensions(oldMethod.getExtraDimensions()); 989 newMethod.setJavadoc(null); 990 int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, Modifier.ABSTRACT | JdtFlags.clearFlag(Modifier.NATIVE | Modifier.FINAL, sourceMethod.getFlags()), adjustments, monitor, false, status); 991 if (oldMethod.isVarargs()) 992 modifiers&= ~Flags.AccVarargs; 993 newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(targetRewrite.getAST(), modifiers)); 994 newMethod.setName(((SimpleName) ASTNode.copySubtree(targetRewrite.getAST(), oldMethod.getName()))); 995 copyReturnType(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping); 996 copyParameters(targetRewrite.getASTRewrite(), getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping); 997 copyThrownExceptions(oldMethod, newMethod); 998 ImportRewriteUtil.addImports(targetRewrite, newMethod, new HashMap (), new HashMap (), false); 999 targetRewrite.getASTRewrite().getListRewrite(destination, destination.getBodyDeclarationsProperty()).insertAt(newMethod, ASTNodes.getInsertionIndex(newMethod, destination.bodyDeclarations()), targetRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_add_abstract_method, SET_PULL_UP)); 1000 } 1001 1002 1005 public Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { 1006 try { 1007 final Map arguments= new HashMap (); 1008 String project= null; 1009 final IType declaring= getDeclaringType(); 1010 final IJavaProject javaProject= declaring.getJavaProject(); 1011 if (javaProject != null) 1012 project= javaProject.getElementName(); 1013 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE; 1014 try { 1015 if (declaring.isLocal() || declaring.isAnonymous()) 1016 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; 1017 } catch (JavaModelException exception) { 1018 JavaPlugin.log(exception); 1019 } 1020 final String description= fMembersToMove.length == 1 ? Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_short, new String [] { fMembersToMove[0].getElementName(), fDestinationType.getElementName()}) : Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_short_multiple, fDestinationType.getElementName()); 1021 final String header= fMembersToMove.length == 1 ? Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description_full, new String [] { JavaElementLabels.getElementLabel(fMembersToMove[0], JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(declaring, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)}) : Messages.format(RefactoringCoreMessages.PullUpRefactoring_descriptor_description, new String [] { JavaElementLabels.getElementLabel(declaring, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 1022 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); 1023 comment.addSetting(Messages.format(RefactoringCoreMessages.MoveStaticMembersProcessor_target_element_pattern, JavaElementLabels.getElementLabel(fDestinationType, JavaElementLabels.ALL_FULLY_QUALIFIED))); 1024 addSuperTypeSettings(comment, true); 1025 final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.PULL_UP, project, description, comment.asString(), arguments, flags); 1026 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fDestinationType)); 1027 arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplace).toString()); 1028 arguments.put(ATTRIBUTE_INSTANCEOF, Boolean.valueOf(fInstanceOf).toString()); 1029 arguments.put(ATTRIBUTE_STUBS, Boolean.valueOf(fCreateMethodStubs).toString()); 1030 arguments.put(ATTRIBUTE_PULL, new Integer (fMembersToMove.length).toString()); 1031 for (int offset= 0; offset < fMembersToMove.length; offset++) 1032 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + 1), descriptor.elementToHandle(fMembersToMove[offset])); 1033 arguments.put(ATTRIBUTE_DELETE, new Integer (fDeletedMethods.length).toString()); 1034 for (int offset= 0; offset < fDeletedMethods.length; offset++) 1035 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + 1), descriptor.elementToHandle(fDeletedMethods[offset])); 1036 arguments.put(ATTRIBUTE_ABSTRACT, new Integer (fAbstractMethods.length).toString()); 1037 for (int offset= 0; offset < fAbstractMethods.length; offset++) 1038 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fMembersToMove.length + fDeletedMethods.length + 1), descriptor.elementToHandle(fAbstractMethods[offset])); 1039 return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.PullUpRefactoring_Pull_Up, fChangeManager.getAllChanges()); 1040 } finally { 1041 monitor.done(); 1042 clearCaches(); 1043 } 1044 } 1045 1046 private TextEditBasedChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException { 1047 Assert.isNotNull(monitor); 1048 Assert.isNotNull(status); 1049 try { 1050 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 24); 1051 final ICompilationUnit source= getDeclaringType().getCompilationUnit(); 1052 final IType destination= getDestinationType(); 1053 final ICompilationUnit target= destination.getCompilationUnit(); 1054 final CompilationUnitRewrite sourceRewriter= getCompilationUnitRewrite(fCompilationUnitRewrites, source); 1055 final CompilationUnitRewrite targetRewriter= getCompilationUnitRewrite(fCompilationUnitRewrites, target); 1056 final Map deleteMap= createMembersToDeleteMap(new SubProgressMonitor(monitor, 1)); 1057 final Map effectedMap= createEffectedTypesMap(new SubProgressMonitor(monitor, 1)); 1058 final ICompilationUnit[] units= getAffectedCompilationUnits(new SubProgressMonitor(monitor, 1)); 1059 ICompilationUnit unit= null; 1060 CompilationUnitRewrite rewrite= null; 1061 final Map adjustments= new HashMap (); 1062 MemberVisibilityAdjustor adjustor= null; 1063 final IProgressMonitor sub= new SubProgressMonitor(monitor, 1); 1064 try { 1065 sub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, units.length * 11); 1066 for (int index= 0; index < units.length; index++) { 1067 unit= units[index]; 1068 if (!(source.equals(unit) || target.equals(unit) || deleteMap.containsKey(unit) || effectedMap.containsKey(unit))) { 1069 sub.worked(10); 1070 continue; 1071 } 1072 rewrite= getCompilationUnitRewrite(fCompilationUnitRewrites, unit); 1073 if (deleteMap.containsKey(unit)) { 1074 LinkedList list= new LinkedList ((List ) deleteMap.get(unit)); 1075 if (destination.isInterface()) { 1076 for (final Iterator iterator= list.iterator(); iterator.hasNext();) { 1077 final IMember member= (IMember) iterator.next(); 1078 if (member instanceof IMethod) 1079 iterator.remove(); 1080 } 1081 } 1082 deleteDeclarationNodes(sourceRewriter, sourceRewriter.getCu().equals(targetRewriter.getCu()), rewrite, list, SET_PULL_UP); 1083 } 1084 final CompilationUnit root= sourceRewriter.getRoot(); 1085 if (unit.equals(target)) { 1086 final ASTRewrite rewriter= rewrite.getASTRewrite(); 1087 if (!JdtFlags.isAbstract(destination) && !destination.isInterface() && getAbstractMethods().length > 0) { 1088 final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(destination, rewrite.getRoot()); 1089 ModifierRewrite.create(rewriter, declaration).setModifiers(declaration.getModifiers() | Modifier.ABSTRACT, rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.PullUpRefactoring_make_target_abstract, SET_PULL_UP)); 1090 } 1091 final TypeVariableMaplet[] mapping= TypeVariableUtil.subTypeToSuperType(getDeclaringType(), destination); 1092 final IProgressMonitor subsub= new SubProgressMonitor(sub, 1); 1093 final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(destination, rewrite.getRoot()); 1094 fMembersToMove= JavaElementUtil.sortByOffset(fMembersToMove); 1095 subsub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fMembersToMove.length); 1096 IMember member= null; 1097 for (int offset= fMembersToMove.length - 1; offset >= 0; offset--) { 1098 member= fMembersToMove[offset]; 1099 adjustor= new MemberVisibilityAdjustor(destination, member); 1100 adjustor.setRewrite(sourceRewriter.getASTRewrite(), root); 1101 1102 adjustor.setFailureSeverity(RefactoringStatus.WARNING); 1104 1105 adjustor.setOwner(fOwner); 1106 adjustor.setRewrites(fCompilationUnitRewrites); 1107 adjustor.setStatus(status); 1108 adjustor.setAdjustments(adjustments); 1109 adjustor.adjustVisibility(new SubProgressMonitor(subsub, 1)); 1110 adjustments.remove(member); 1111 if (member instanceof IField) { 1112 final VariableDeclarationFragment oldField= ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, root); 1113 if (oldField != null) { 1114 int flags= getModifiersWithUpdatedVisibility(member, member.getFlags(), adjustments, new SubProgressMonitor(subsub, 1), true, status); 1115 if (destination.isInterface()) 1116 flags|= Flags.AccFinal; 1117 final FieldDeclaration newField= createNewFieldDeclarationNode(rewriter, root, (IField) member, oldField, mapping, new SubProgressMonitor(subsub, 1), status, flags); 1118 rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newField, ASTNodes.getInsertionIndex(newField, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP)); 1119 ImportRewriteUtil.addImports(rewrite, oldField.getParent(), new HashMap (), new HashMap (), false); 1120 } 1121 } else if (member instanceof IMethod) { 1122 final MethodDeclaration oldMethod= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, root); 1123 if (oldMethod != null) { 1124 if (JdtFlags.isStatic(member) && fDestinationType.isInterface()) 1125 status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_moving_static_method_to_interface, new String [] { JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(member))); 1126 final MethodDeclaration newMethod= createNewMethodDeclarationNode(sourceRewriter, rewrite, ((IMethod) member), oldMethod, root, mapping, adjustments, new SubProgressMonitor(subsub, 1), status); 1127 rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newMethod, ASTNodes.getInsertionIndex(newMethod, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP)); 1128 ImportRewriteUtil.addImports(rewrite, oldMethod, new HashMap (), new HashMap (), false); 1129 } 1130 } else if (member instanceof IType) { 1131 final AbstractTypeDeclaration oldType= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, root); 1132 if (oldType != null) { 1133 final BodyDeclaration newType= createNewTypeDeclarationNode(((IType) member), oldType, root, mapping, rewriter); 1134 rewriter.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertAt(newType, ASTNodes.getInsertionIndex(newType, declaration.bodyDeclarations()), rewrite.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_add_member, SET_PULL_UP)); 1135 ImportRewriteUtil.addImports(rewrite, oldType, new HashMap (), new HashMap (), false); 1136 } 1137 } else 1138 Assert.isTrue(false); 1139 subsub.worked(1); 1140 } 1141 subsub.done(); 1142 for (int offset= 0; offset < fAbstractMethods.length; offset++) 1143 createAbstractMethod(fAbstractMethods[offset], sourceRewriter, root, declaration, mapping, rewrite, adjustments, new SubProgressMonitor(sub, 1), status); 1144 } else 1145 sub.worked(2); 1146 if (unit.equals(sourceRewriter.getCu())) { 1147 final IProgressMonitor subsub= new SubProgressMonitor(sub, 1); 1148 subsub.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, fAbstractMethods.length * 2); 1149 IMethod method= null; 1150 for (int offset= 0; offset < fAbstractMethods.length; offset++) { 1151 method= fAbstractMethods[offset]; 1152 adjustor= new MemberVisibilityAdjustor(destination, method); 1153 adjustor.setRewrite(sourceRewriter.getASTRewrite(), root); 1154 adjustor.setRewrites(fCompilationUnitRewrites); 1155 1156 adjustor.setFailureSeverity(RefactoringStatus.WARNING); 1158 1159 adjustor.setOwner(fOwner); 1160 adjustor.setStatus(status); 1161 adjustor.setAdjustments(adjustments); 1162 if (needsVisibilityAdjustment(method, false, new SubProgressMonitor(subsub, 1), status)) 1163 adjustments.put(method, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(method, Modifier.ModifierKeyword.PROTECTED_KEYWORD, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning, new String [] { MemberVisibilityAdjustor.getLabel(method), RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_protected}), JavaStatusContext.create(method)))); 1164 } 1165 } else 1166 sub.worked(2); 1167 if (effectedMap.containsKey(unit)) 1168 addNecessaryMethodStubs((List ) effectedMap.get(unit), root, rewrite, adjustments, new SubProgressMonitor(sub, 2), status); 1169 if (sub.isCanceled()) 1170 throw new OperationCanceledException(); 1171 } 1172 } finally { 1173 sub.done(); 1174 } 1175 if (adjustor != null && !adjustments.isEmpty()) 1176 adjustor.rewriteVisibility(new SubProgressMonitor(monitor, 1)); 1177 final TextEditBasedChangeManager manager= new TextEditBasedChangeManager(); 1178 if (fReplace) { 1179 final Set set= fCompilationUnitRewrites.keySet(); 1180 for (final Iterator iterator= set.iterator(); iterator.hasNext();) { 1181 unit= (ICompilationUnit) iterator.next(); 1182 rewrite= (CompilationUnitRewrite) fCompilationUnitRewrites.get(unit); 1183 if (rewrite != null) { 1184 final CompilationUnitChange change= rewrite.createChange(false, null); 1185 if (change != null) 1186 manager.manage(unit, change); 1187 } 1188 } 1189 TextEdit edit= null; 1190 TextEditBasedChange change= null; 1191 final Map workingcopies= new HashMap (); 1192 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1); 1193 try { 1194 subMonitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, set.size()); 1195 for (final Iterator iterator= set.iterator(); iterator.hasNext();) { 1196 unit= (ICompilationUnit) iterator.next(); 1197 change= manager.get(unit); 1198 if (change instanceof TextChange) { 1199 edit= ((TextChange) change).getEdit(); 1200 if (edit != null) { 1201 final ICompilationUnit copy= createWorkingCopy(unit, edit, status, new SubProgressMonitor(monitor, 1)); 1202 if (copy != null) 1203 workingcopies.put(unit, copy); 1204 } 1205 } 1206 } 1207 final ICompilationUnit current= (ICompilationUnit) workingcopies.get(sourceRewriter.getCu()); 1208 if (current != null) 1209 rewriteTypeOccurrences(manager, sourceRewriter, current, new HashSet (), status, new SubProgressMonitor(monitor, 16)); 1210 } finally { 1211 subMonitor.done(); 1212 ICompilationUnit[] cus= manager.getAllCompilationUnits(); 1213 for (int index= 0; index < cus.length; index++) { 1214 CompilationUnitChange current= (CompilationUnitChange) manager.get(cus[index]); 1215 if (change != null && current.getEdit() == null) 1216 manager.remove(cus[index]); 1217 } 1218 } 1219 } 1220 registerChanges(manager); 1221 return manager; 1222 } finally { 1223 fCompilationUnitRewrites.clear(); 1224 monitor.done(); 1225 } 1226 } 1227 1228 private Map createEffectedTypesMap(final IProgressMonitor monitor) throws JavaModelException { 1229 if (!(fCreateMethodStubs && getAbstractMethods().length > 0)) 1230 return new HashMap (0); 1231 final Set effected= getEffectedSubTypes(getDestinationTypeHierarchy(monitor), getDestinationType()); 1232 final Map result= new HashMap (); 1233 for (final Iterator iterator= effected.iterator(); iterator.hasNext();) { 1234 final IType type= (IType) iterator.next(); 1235 final ICompilationUnit unit= type.getCompilationUnit(); 1236 if (!result.containsKey(unit)) 1237 result.put(unit, new ArrayList (1)); 1238 ((List ) result.get(unit)).add(type); 1239 } 1240 return result; 1241 } 1242 1243 private Javadoc createJavadocForStub(final String enclosingTypeName, final MethodDeclaration oldMethod, final MethodDeclaration newMethodNode, final ICompilationUnit cu, final ASTRewrite rewrite) throws CoreException { 1244 if (fSettings.createComments) { 1245 final IMethodBinding binding= oldMethod.resolveBinding(); 1246 if (binding != null) { 1247 final ITypeBinding[] params= binding.getParameterTypes(); 1248 final String fullTypeName= JavaModelUtil.getFullyQualifiedName(getDestinationType()); 1249 final String [] fullParamNames= new String [params.length]; 1250 for (int i= 0; i < fullParamNames.length; i++) { 1251 fullParamNames[i]= Bindings.getFullyQualifiedName(params[i]); 1252 } 1253 final String comment= CodeGeneration.getMethodComment(cu, enclosingTypeName, newMethodNode, false, binding.getName(), fullTypeName, fullParamNames, StubUtility.getLineDelimiterUsed(cu)); 1254 return (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC); 1255 } 1256 } 1257 return null; 1258 } 1259 1260 private Map createMembersToDeleteMap(final IProgressMonitor monitor) throws JavaModelException { 1261 final IMember[] membersToDelete= getMembersToDelete(monitor); 1262 final Map result= new HashMap (); 1263 for (int i= 0; i < membersToDelete.length; i++) { 1264 final IMember member= membersToDelete[i]; 1265 final ICompilationUnit cu= member.getCompilationUnit(); 1266 if (!result.containsKey(cu)) 1267 result.put(cu, new ArrayList (1)); 1268 ((List ) result.get(cu)).add(member); 1269 } 1270 return result; 1271 } 1272 1273 private MethodDeclaration createNewMethodDeclarationNode(final CompilationUnitRewrite sourceRewrite, final CompilationUnitRewrite targetRewrite, final IMethod sourceMethod, final MethodDeclaration oldMethod, final CompilationUnit declaringCuNode, final TypeVariableMaplet[] mapping, final Map adjustments, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException { 1274 final ASTRewrite rewrite= targetRewrite.getASTRewrite(); 1275 final AST ast= rewrite.getAST(); 1276 final MethodDeclaration newMethod= ast.newMethodDeclaration(); 1277 if (!getDestinationType().isInterface()) 1278 copyBodyOfPulledUpMethod(sourceRewrite, targetRewrite, sourceMethod, oldMethod, newMethod, mapping, monitor); 1279 newMethod.setConstructor(oldMethod.isConstructor()); 1280 newMethod.setExtraDimensions(oldMethod.getExtraDimensions()); 1281 copyJavadocNode(rewrite, sourceMethod, oldMethod, newMethod); 1282 int modifiers= getModifiersWithUpdatedVisibility(sourceMethod, sourceMethod.getFlags(), adjustments, monitor, true, status); 1283 if (oldMethod.isVarargs()) 1284 modifiers&= ~Flags.AccVarargs; 1285 copyAnnotations(oldMethod, newMethod); 1286 newMethod.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers)); 1287 newMethod.setName(((SimpleName) ASTNode.copySubtree(ast, oldMethod.getName()))); 1288 copyReturnType(rewrite, getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping); 1289 copyParameters(rewrite, getDeclaringType().getCompilationUnit(), oldMethod, newMethod, mapping); 1290 copyThrownExceptions(oldMethod, newMethod); 1291 copyTypeParameters(oldMethod, newMethod); 1292 return newMethod; 1293 } 1294 1295 private BodyDeclaration createNewTypeDeclarationNode(final IType type, final AbstractTypeDeclaration oldType, final CompilationUnit declaringCuNode, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException { 1296 final ICompilationUnit declaringCu= getDeclaringType().getCompilationUnit(); 1297 if (!JdtFlags.isPublic(type) && !JdtFlags.isProtected(type)) { 1298 if (mapping.length > 0) 1299 return createPlaceholderForTypeDeclaration(oldType, declaringCu, mapping, rewrite, true); 1300 1301 return createPlaceholderForProtectedTypeDeclaration(oldType, declaringCuNode, declaringCu, rewrite, true); 1302 } 1303 if (mapping.length > 0) 1304 return createPlaceholderForTypeDeclaration(oldType, declaringCu, mapping, rewrite, true); 1305 1306 return createPlaceholderForTypeDeclaration(oldType, declaringCu, rewrite, true); 1307 } 1308 1309 private ICompilationUnit createWorkingCopy(final ICompilationUnit unit, final TextEdit edit, final RefactoringStatus status, final IProgressMonitor monitor) { 1310 try { 1311 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1); 1312 final ICompilationUnit copy= getSharedWorkingCopy(unit.getPrimary(), new SubProgressMonitor(monitor, 1)); 1313 final IDocument document= new Document(unit.getBuffer().getContents()); 1314 edit.apply(document, TextEdit.UPDATE_REGIONS); 1315 copy.getBuffer().setContents(document.get()); 1316 JavaModelUtil.reconcile(copy); 1317 return copy; 1318 } catch (JavaModelException exception) { 1319 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1320 } catch (MalformedTreeException exception) { 1321 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1322 } catch (BadLocationException exception) { 1323 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1324 } finally { 1325 monitor.done(); 1326 } 1327 return null; 1328 } 1329 1330 1337 protected RefactoringStatus createWorkingCopyLayer(IProgressMonitor monitor) { 1338 try { 1339 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1); 1340 ICompilationUnit unit= getDeclaringType().getCompilationUnit(); 1341 if (fLayer) 1342 unit= unit.findWorkingCopy(fOwner); 1343 resetWorkingCopies(unit); 1344 return new RefactoringStatus(); 1345 } finally { 1346 monitor.done(); 1347 } 1348 } 1349 1350 private IMethod[] getAbstractMethods() throws JavaModelException { 1351 final IMethod[] toDeclareAbstract= fAbstractMethods; 1352 final IMethod[] abstractPulledUp= getAbstractMethodsToPullUp(); 1353 final Set result= new LinkedHashSet (toDeclareAbstract.length + abstractPulledUp.length + fMembersToMove.length); 1354 if (fDestinationType.isInterface()) { 1355 for (int i= 0; i < fMembersToMove.length; i++) { 1356 if (fMembersToMove[i].getElementType() == IJavaElement.METHOD) { 1357 result.add(fMembersToMove[i]); 1358 } 1359 } 1360 } 1361 result.addAll(Arrays.asList(toDeclareAbstract)); 1362 result.addAll(Arrays.asList(abstractPulledUp)); 1363 return (IMethod[]) result.toArray(new IMethod[result.size()]); 1364 } 1365 1366 private IMethod[] getAbstractMethodsToPullUp() throws JavaModelException { 1367 final List result= new ArrayList (fMembersToMove.length); 1368 for (int i= 0; i < fMembersToMove.length; i++) { 1369 final IMember member= fMembersToMove[i]; 1370 if (member instanceof IMethod && JdtFlags.isAbstract(member)) 1371 result.add(member); 1372 } 1373 return (IMethod[]) result.toArray(new IMethod[result.size()]); 1374 } 1375 1376 public IMember[] getAdditionalRequiredMembersToPullUp(final IProgressMonitor monitor) throws JavaModelException { 1377 final IMember[] members= getCreatedDestinationMembers(); 1378 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_calculating_required, members.length); final List queue= new ArrayList (members.length); 1380 queue.addAll(Arrays.asList(members)); 1381 if (queue.isEmpty()) 1382 return new IMember[0]; 1383 int i= 0; 1384 IMember current; 1385 do { 1386 current= (IMember) queue.get(i); 1387 addAllRequiredPullableMembers(queue, current, new SubProgressMonitor(monitor, 1)); 1388 i++; 1389 if (queue.size() == i) 1390 current= null; 1391 } while (current != null); 1392 queue.removeAll(Arrays.asList(members)); return (IMember[]) queue.toArray(new IMember[queue.size()]); 1394 } 1395 1396 private ICompilationUnit[] getAffectedCompilationUnits(final IProgressMonitor monitor) throws JavaModelException { 1397 final IType[] allSubtypes= getDestinationTypeHierarchy(monitor).getAllSubtypes(getDestinationType()); 1398 final Set result= new HashSet (allSubtypes.length); 1399 for (int i= 0; i < allSubtypes.length; i++) { 1400 result.add(allSubtypes[i].getCompilationUnit()); 1401 } 1402 result.add(getDestinationType().getCompilationUnit()); 1403 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 1404 } 1405 1406 public IType[] getCandidateTypes(final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException { 1407 final IType declaring= getDeclaringType(); 1408 final IType[] superTypes= declaring.newSupertypeHierarchy(fOwner, monitor).getAllSupertypes(declaring); 1409 final List list= new ArrayList (superTypes.length); 1410 int binary= 0; 1411 for (int index= 0; index < superTypes.length; index++) { 1412 final IType type= superTypes[index]; 1413 if (type != null && type.exists() && !type.isReadOnly() && !type.isBinary() && !"java.lang.Object".equals(type.getFullyQualifiedName())) { list.add(type); 1415 } else { 1416 if (type != null && type.isBinary()) { 1417 binary++; 1418 } 1419 } 1420 } 1421 if (superTypes.length == 1 && superTypes[0].getFullyQualifiedName().equals("java.lang.Object")) status.addFatalError(RefactoringCoreMessages.PullUPRefactoring_not_java_lang_object); 1423 else if (superTypes.length == binary) 1424 status.addFatalError(RefactoringCoreMessages.PullUPRefactoring_no_all_binary); 1425 1426 Collections.reverse(list); 1427 return (IType[]) list.toArray(new IType[list.size()]); 1428 } 1429 1430 protected CompilationUnitRewrite getCompilationUnitRewrite(final Map rewrites, final ICompilationUnit unit) { 1431 Assert.isNotNull(rewrites); 1432 Assert.isNotNull(unit); 1433 CompilationUnitRewrite rewrite= (CompilationUnitRewrite) rewrites.get(unit); 1434 if (rewrite == null) { 1435 rewrite= new CompilationUnitRewrite(fOwner, unit); 1436 rewrites.put(unit, rewrite); 1437 } 1438 return rewrite; 1439 } 1440 1441 private IMember[] getCreatedDestinationMembers() { 1442 final List result= new ArrayList (fMembersToMove.length + fAbstractMethods.length); 1443 result.addAll(Arrays.asList(fMembersToMove)); 1444 result.addAll(Arrays.asList(fAbstractMethods)); 1445 return (IMember[]) result.toArray(new IMember[result.size()]); 1446 } 1447 1448 public boolean getCreateMethodStubs() { 1449 return fCreateMethodStubs; 1450 } 1451 1452 public ITypeHierarchy getDeclaringSuperTypeHierarchy(final IProgressMonitor monitor) throws JavaModelException { 1453 try { 1454 if (fCachedDeclaringSuperTypeHierarchy != null) 1455 return fCachedDeclaringSuperTypeHierarchy; 1456 fCachedDeclaringSuperTypeHierarchy= getDeclaringType().newSupertypeHierarchy(fOwner, monitor); 1457 return fCachedDeclaringSuperTypeHierarchy; 1458 } finally { 1459 monitor.done(); 1460 } 1461 } 1462 1463 public IType getDestinationType() { 1464 return fDestinationType; 1465 } 1466 1467 public ITypeHierarchy getDestinationTypeHierarchy(final IProgressMonitor monitor) throws JavaModelException { 1468 try { 1469 if (fCachedDestinationTypeHierarchy != null && fCachedDestinationTypeHierarchy.getType().equals(getDestinationType())) 1470 return fCachedDestinationTypeHierarchy; 1471 fCachedDestinationTypeHierarchy= getDestinationType().newTypeHierarchy(fOwner, monitor); 1472 return fCachedDestinationTypeHierarchy; 1473 } finally { 1474 monitor.done(); 1475 } 1476 } 1477 1478 1481 public Object [] getElements() { 1482 return fMembersToMove; 1483 } 1484 1485 1488 public String getIdentifier() { 1489 return IDENTIFIER; 1490 } 1491 1492 public IMember[] getMatchingElements(final IProgressMonitor monitor, final boolean includeAbstract) throws JavaModelException { 1493 try { 1494 final Set result= new HashSet (); 1495 final IType destination= getDestinationType(); 1496 final Map matching= getMatchingMembers(getDestinationTypeHierarchy(monitor), getDestinationType(), includeAbstract); 1497 for (final Iterator iterator= matching.keySet().iterator(); iterator.hasNext();) { 1498 final IMember key= (IMember) iterator.next(); 1499 Assert.isTrue(!key.getDeclaringType().equals(destination)); 1500 result.addAll((Set ) matching.get(key)); 1501 } 1502 return (IMember[]) result.toArray(new IMember[result.size()]); 1503 } finally { 1504 monitor.done(); 1505 } 1506 } 1507 1508 private Map getMatchingMembers(final ITypeHierarchy hierarchy, final IType type, final boolean includeAbstract) throws JavaModelException { 1509 final Map result= new HashMap (); 1510 result.putAll(getMatchingMembersMapping(type)); 1511 final IType[] subTypes= hierarchy.getAllSubtypes(type); 1512 for (int i= 0; i < subTypes.length; i++) { 1513 final Map map= getMatchingMembersMapping(subTypes[i]); 1514 mergeMaps(result, map); 1515 upgradeMap(result, map); 1516 } 1517 if (includeAbstract) 1518 return result; 1519 1520 for (int i= 0; i < fAbstractMethods.length; i++) { 1521 if (result.containsKey(fAbstractMethods[i])) 1522 result.remove(fAbstractMethods[i]); 1523 } 1524 return result; 1525 } 1526 1527 private Map getMatchingMembersMapping(final IType initial) throws JavaModelException { 1528 final Map result= new HashMap (); 1529 final IMember[] members= getCreatedDestinationMembers(); 1530 for (int i= 0; i < members.length; i++) { 1531 final IMember member= members[i]; 1532 if (member instanceof IMethod) { 1533 final IMethod method= (IMethod) member; 1534 final IMethod found= MemberCheckUtil.findMethod(method, initial.getMethods()); 1535 if (found != null) 1536 addMatchingMember(result, method, found); 1537 } else if (member instanceof IField) { 1538 final IField field= (IField) member; 1539 final IField found= initial.getField(field.getElementName()); 1540 if (found.exists()) 1541 addMatchingMember(result, field, found); 1542 } else if (member instanceof IType) { 1543 final IType type= (IType) member; 1544 final IType found= initial.getType(type.getElementName()); 1545 if (found.exists()) 1546 addMatchingMember(result, type, found); 1547 } else 1548 Assert.isTrue(false); 1549 } 1550 1551 return result; 1552 } 1553 1554 private IMember[] getMembersToDelete(final IProgressMonitor monitor) throws JavaModelException { 1555 try { 1556 final IMember[] typesToDelete= getMembers(fMembersToMove, IJavaElement.TYPE); 1557 final IMember[] matchingElements= getMatchingElements(monitor, false); 1558 final IMember[] matchingFields= getMembers(matchingElements, IJavaElement.FIELD); 1559 return JavaElementUtil.merge(JavaElementUtil.merge(matchingFields, typesToDelete), fDeletedMethods); 1560 } finally { 1561 monitor.done(); 1562 } 1563 } 1564 1565 private int getModifiersWithUpdatedVisibility(final IMember member, final int modifiers, final Map adjustments, final IProgressMonitor monitor, final boolean considerReferences, final RefactoringStatus status) throws JavaModelException { 1566 if (needsVisibilityAdjustment(member, considerReferences, monitor, status)) { 1567 final MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment adjustment= new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(member, Modifier.ModifierKeyword.PROTECTED_KEYWORD, RefactoringStatus.createWarningStatus(Messages.format(MemberVisibilityAdjustor.getMessage(member), new String [] { MemberVisibilityAdjustor.getLabel(member), MemberVisibilityAdjustor.getLabel(Modifier.ModifierKeyword.PROTECTED_KEYWORD)}))); 1568 adjustment.setNeedsRewriting(false); 1569 adjustments.put(member, adjustment); 1570 return JdtFlags.clearAccessModifiers(modifiers) | Modifier.PROTECTED; 1571 } 1572 if (getDestinationType().isInterface()) { 1573 final int flags= JdtFlags.clearAccessModifiers(modifiers) | Modifier.PUBLIC; 1574 if (member instanceof IMethod) 1575 return JdtFlags.clearFlag(Modifier.STATIC, flags); 1576 return flags; 1577 } 1578 return modifiers; 1579 } 1580 1581 private Set getNotDeletedMembers(final IProgressMonitor monitor) throws JavaModelException { 1582 final Set matchingSet= new HashSet (); 1583 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 2); 1584 matchingSet.addAll(Arrays.asList(getMatchingElements(new SubProgressMonitor(monitor, 1), true))); 1585 matchingSet.removeAll(Arrays.asList(getMembersToDelete(new SubProgressMonitor(monitor, 1)))); 1586 monitor.done(); 1587 return matchingSet; 1588 } 1589 1590 1593 public String getProcessorName() { 1594 return RefactoringCoreMessages.PullUpRefactoring_Pull_Up; 1595 } 1596 1597 public IMember[] getPullableMembersOfDeclaringType() { 1598 try { 1599 return RefactoringAvailabilityTester.getPullUpMembers(getDeclaringType()); 1600 } catch (JavaModelException e) { 1601 return new IMember[0]; 1602 } 1603 } 1604 1605 private Set getSkippedSuperTypes(final IProgressMonitor monitor) throws JavaModelException { 1609 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 1); 1610 try { 1611 if (fCachedSkippedSuperTypes != null && getDestinationTypeHierarchy(new SubProgressMonitor(monitor, 1)).getType().equals(getDestinationType())) 1612 return fCachedSkippedSuperTypes; 1613 final ITypeHierarchy hierarchy= getDestinationTypeHierarchy(new SubProgressMonitor(monitor, 1)); 1614 fCachedSkippedSuperTypes= new HashSet (2); 1615 IType current= hierarchy.getSuperclass(getDeclaringType()); 1616 while (current != null && !current.equals(getDestinationType())) { 1617 fCachedSkippedSuperTypes.add(current); 1618 current= hierarchy.getSuperclass(current); 1619 } 1620 return fCachedSkippedSuperTypes; 1621 } finally { 1622 monitor.done(); 1623 } 1624 } 1625 1626 1629 public RefactoringStatus initialize(final RefactoringArguments arguments) { 1630 if (arguments instanceof JavaRefactoringArguments) { 1631 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 1632 String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 1633 if (handle != null) { 1634 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1635 if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) 1636 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.PULL_UP); 1637 else 1638 fDestinationType= (IType) element; 1639 } else 1640 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 1641 final String stubs= extended.getAttribute(ATTRIBUTE_STUBS); 1642 if (stubs != null) { 1643 fCreateMethodStubs= Boolean.valueOf(stubs).booleanValue(); 1644 } else 1645 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STUBS)); 1646 final String instance= extended.getAttribute(ATTRIBUTE_INSTANCEOF); 1647 if (instance != null) { 1648 fInstanceOf= Boolean.valueOf(instance).booleanValue(); 1649 } else 1650 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INSTANCEOF)); 1651 final String replace= extended.getAttribute(ATTRIBUTE_REPLACE); 1652 if (replace != null) { 1653 fReplace= Boolean.valueOf(replace).booleanValue(); 1654 } else 1655 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE)); 1656 int pullCount= 0; 1657 int abstractCount= 0; 1658 int deleteCount= 0; 1659 String value= extended.getAttribute(ATTRIBUTE_ABSTRACT); 1660 if (value != null && !"".equals(value)) { try { 1662 abstractCount= Integer.parseInt(value); 1663 } catch (NumberFormatException exception) { 1664 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT)); 1665 } 1666 } else 1667 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ABSTRACT)); 1668 value= extended.getAttribute(ATTRIBUTE_DELETE); 1669 if (value != null && !"".equals(value)) { try { 1671 deleteCount= Integer.parseInt(value); 1672 } catch (NumberFormatException exception) { 1673 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE)); 1674 } 1675 } else 1676 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE)); 1677 value= extended.getAttribute(ATTRIBUTE_PULL); 1678 if (value != null && !"".equals(value)) { try { 1680 pullCount= Integer.parseInt(value); 1681 } catch (NumberFormatException exception) { 1682 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PULL)); 1683 } 1684 } else 1685 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_PULL)); 1686 final RefactoringStatus status= new RefactoringStatus(); 1687 List elements= new ArrayList (); 1688 for (int index= 0; index < pullCount; index++) { 1689 final String attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1); 1690 handle= extended.getAttribute(attribute); 1691 if (handle != null && !"".equals(handle)) { final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1693 if (element == null || !element.exists()) 1694 status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.PULL_UP)); 1695 else 1696 elements.add(element); 1697 } else 1698 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute)); 1699 } 1700 fMembersToMove= (IMember[]) elements.toArray(new IMember[elements.size()]); 1701 elements= new ArrayList (); 1702 for (int index= 0; index < deleteCount; index++) { 1703 final String attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (pullCount + index + 1); 1704 handle= extended.getAttribute(attribute); 1705 if (handle != null && !"".equals(handle)) { final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1707 if (element == null || !element.exists()) 1708 status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.PULL_UP)); 1709 else 1710 elements.add(element); 1711 } else 1712 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute)); 1713 } 1714 fDeletedMethods= (IMethod[]) elements.toArray(new IMethod[elements.size()]); 1715 elements= new ArrayList (); 1716 for (int index= 0; index < abstractCount; index++) { 1717 final String attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (pullCount + abstractCount + index + 1); 1718 handle= extended.getAttribute(attribute); 1719 if (handle != null && !"".equals(handle)) { final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 1721 if (element == null || !element.exists()) 1722 status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.PULL_UP)); 1723 else 1724 elements.add(element); 1725 } else 1726 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute)); 1727 } 1728 fAbstractMethods= (IMethod[]) elements.toArray(new IMethod[elements.size()]); 1729 IJavaProject project= null; 1730 if (fMembersToMove.length > 0) 1731 project= fMembersToMove[0].getJavaProject(); 1732 fSettings= JavaPreferencesSettings.getCodeGenerationSettings(project); 1733 if (!status.isOK()) 1734 return status; 1735 } else 1736 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 1737 return new RefactoringStatus(); 1738 } 1739 1740 1743 public boolean isApplicable() throws CoreException { 1744 return RefactoringAvailabilityTester.isPullUpAvailable(fMembersToMove); 1745 } 1746 1747 private boolean isAvailableInDestination(final IMethod method, final IProgressMonitor monitor) throws JavaModelException { 1748 try { 1749 final IType destination= getDestinationType(); 1750 final IMethod first= JavaModelUtil.findMethod(method.getElementName(), method.getParameterTypes(), false, destination); 1751 if (first != null && MethodChecks.isVirtual(first)) 1752 return true; 1753 final ITypeHierarchy hierarchy= getDestinationTypeHierarchy(monitor); 1754 final IMethod found= JavaModelUtil.findMethodInHierarchy(hierarchy, destination, method.getElementName(), method.getParameterTypes(), false); 1755 return found != null && MethodChecks.isVirtual(found); 1756 } finally { 1757 monitor.done(); 1758 } 1759 } 1760 1761 private boolean isRequiredPullableMember(final List queue, final IMember member) throws JavaModelException { 1762 final IType declaring= member.getDeclaringType(); 1763 if (declaring == null) return false; 1765 return declaring.equals(getDeclaringType()) && !queue.contains(member) && RefactoringAvailabilityTester.isPullUpAvailable(member); 1766 } 1767 1768 protected void registerChanges(final TextEditBasedChangeManager manager) throws CoreException { 1769 ICompilationUnit unit= null; 1770 CompilationUnitRewrite rewrite= null; 1771 for (final Iterator iterator= fCompilationUnitRewrites.keySet().iterator(); iterator.hasNext();) { 1772 unit= (ICompilationUnit) iterator.next(); 1773 rewrite= (CompilationUnitRewrite) fCompilationUnitRewrites.get(unit); 1774 if (rewrite != null) { 1775 final CompilationUnitChange change= rewrite.createChange(); 1776 if (change != null) 1777 manager.manage(unit, change); 1778 } 1779 } 1780 } 1781 1782 1785 public void resetEnvironment() { 1786 ICompilationUnit unit= getDeclaringType().getCompilationUnit(); 1787 if (fLayer) 1788 unit= unit.findWorkingCopy(fOwner); 1789 resetWorkingCopies(unit); 1790 } 1791 1792 1795 protected void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final ASTRequestor requestor, final CompilationUnitRewrite rewrite, final ICompilationUnit unit, final CompilationUnit node, final Set replacements, final IProgressMonitor monitor) throws CoreException { 1796 try { 1797 monitor.beginTask("", 100); monitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 1799 CompilationUnitRewrite currentRewrite= null; 1800 final CompilationUnitRewrite existingRewrite= (CompilationUnitRewrite) fCompilationUnitRewrites.get(unit.getPrimary()); 1801 final boolean isTouched= existingRewrite != null; 1802 if (isTouched) 1803 currentRewrite= existingRewrite; 1804 else 1805 currentRewrite= new CompilationUnitRewrite(unit, node); 1806 final Collection collection= (Collection ) fTypeOccurrences.get(unit); 1807 if (collection != null && !collection.isEmpty()) { 1808 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100); 1809 try { 1810 subMonitor.beginTask("", collection.size() * 10); subMonitor.setTaskName(RefactoringCoreMessages.ExtractInterfaceProcessor_creating); 1812 TType estimate= null; 1813 ISourceConstraintVariable variable= null; 1814 ITypeConstraintVariable constraint= null; 1815 for (final Iterator iterator= collection.iterator(); iterator.hasNext();) { 1816 variable= (ISourceConstraintVariable) iterator.next(); 1817 if (variable instanceof ITypeConstraintVariable) { 1818 constraint= (ITypeConstraintVariable) variable; 1819 estimate= (TType) constraint.getData(SuperTypeConstraintsSolver.DATA_TYPE_ESTIMATE); 1820 if (estimate != null) { 1821 final CompilationUnitRange range= constraint.getRange(); 1822 if (isTouched) 1823 rewriteTypeOccurrence(range, estimate, requestor, currentRewrite, node, replacements, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); 1824 else { 1825 final ASTNode result= NodeFinder.perform(node, range.getSourceRange()); 1826 if (result != null) 1827 rewriteTypeOccurrence(estimate, currentRewrite, result, currentRewrite.createCategorizedGroupDescription(RefactoringCoreMessages.SuperTypeRefactoringProcessor_update_type_occurrence, SET_SUPER_TYPE)); 1828 } 1829 subMonitor.worked(10); 1830 } 1831 } 1832 } 1833 } finally { 1834 subMonitor.done(); 1835 } 1836 } 1837 if (!isTouched) { 1838 final TextChange change= currentRewrite.createChange(); 1839 if (change != null) 1840 manager.manage(unit, change); 1841 } 1842 } finally { 1843 monitor.done(); 1844 } 1845 } 1846 1847 protected void rewriteTypeOccurrences(final TextEditBasedChangeManager manager, final CompilationUnitRewrite sourceRewrite, final ICompilationUnit copy, final Set replacements, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException { 1848 try { 1849 monitor.beginTask("", 100); monitor.setTaskName(RefactoringCoreMessages.PullUpRefactoring_checking); 1851 final IType declaring= getDeclaringType(); 1852 final IJavaProject project= declaring.getJavaProject(); 1853 final ASTParser parser= ASTParser.newParser(AST.JLS3); 1854 parser.setWorkingCopyOwner(fOwner); 1855 parser.setResolveBindings(true); 1856 parser.setProject(project); 1857 parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project)); 1858 parser.createASTs(new ICompilationUnit[] { copy}, new String [0], new ASTRequestor() { 1859 1860 public final void acceptAST(final ICompilationUnit unit, final CompilationUnit node) { 1861 try { 1862 final IType subType= (IType) JavaModelUtil.findInCompilationUnit(unit, declaring); 1863 final AbstractTypeDeclaration subDeclaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subType, node); 1864 if (subDeclaration != null) { 1865 final ITypeBinding subBinding= subDeclaration.resolveBinding(); 1866 if (subBinding != null) { 1867 String name= null; 1868 ITypeBinding superBinding= null; 1869 final ITypeBinding[] superBindings= Bindings.getAllSuperTypes(subBinding); 1870 for (int index= 0; index < superBindings.length; index++) { 1871 name= superBindings[index].getName(); 1872 if (name.startsWith(fDestinationType.getElementName())) 1873 superBinding= superBindings[index]; 1874 } 1875 if (superBinding != null) { 1876 solveSuperTypeConstraints(unit, node, subType, subBinding, superBinding, new SubProgressMonitor(monitor, 80), status); 1877 if (!status.hasFatalError()) 1878 rewriteTypeOccurrences(manager, this, sourceRewrite, unit, node, replacements, status, new SubProgressMonitor(monitor, 120)); 1879 } 1880 } 1881 } 1882 } catch (JavaModelException exception) { 1883 JavaPlugin.log(exception); 1884 status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractInterfaceProcessor_internal_error)); 1885 } 1886 } 1887 1888 public final void acceptBinding(final String key, final IBinding binding) { 1889 } 1891 }, new NullProgressMonitor()); 1892 } finally { 1893 monitor.done(); 1894 } 1895 } 1896 1897 1903 public void setAbstractMethods(final IMethod[] methods) { 1904 Assert.isNotNull(methods); 1905 fAbstractMethods= methods; 1906 } 1907 1908 1916 public void setCreateMethodStubs(final boolean create) { 1917 fCreateMethodStubs= create; 1918 } 1919 1920 1926 public void setDeletedMethods(final IMethod[] methods) { 1927 Assert.isNotNull(methods); 1928 fDeletedMethods= methods; 1929 } 1930 1931 1937 public void setDestinationType(final IType type) { 1938 Assert.isNotNull(type); 1939 if (!type.equals(fDestinationType)) 1940 fCachedDestinationTypeHierarchy= null; 1941 fDestinationType= type; 1942 } 1943 1944 1950 public void setMembersToMove(final IMember[] members) { 1951 Assert.isNotNull(members); 1952 fMembersToMove= (IMember[]) SourceReferenceUtil.sortByOffset(members); 1953 } 1954} 1955 | Popular Tags |