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