1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 20 import org.eclipse.text.edits.MalformedTreeException; 21 import org.eclipse.text.edits.TextEdit; 22 23 import org.eclipse.core.runtime.Assert; 24 import org.eclipse.core.runtime.CoreException; 25 import org.eclipse.core.runtime.IProgressMonitor; 26 import org.eclipse.core.runtime.NullProgressMonitor; 27 import org.eclipse.core.runtime.SubProgressMonitor; 28 29 import org.eclipse.jface.text.BadLocationException; 30 import org.eclipse.jface.text.Document; 31 import org.eclipse.jface.text.IDocument; 32 import org.eclipse.jface.text.TextUtilities; 33 34 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 35 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 36 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 37 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; 38 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; 39 40 import org.eclipse.jdt.core.Flags; 41 import org.eclipse.jdt.core.ICompilationUnit; 42 import org.eclipse.jdt.core.IField; 43 import org.eclipse.jdt.core.IInitializer; 44 import org.eclipse.jdt.core.IJavaElement; 45 import org.eclipse.jdt.core.IMember; 46 import org.eclipse.jdt.core.IMethod; 47 import org.eclipse.jdt.core.ISourceRange; 48 import org.eclipse.jdt.core.IType; 49 import org.eclipse.jdt.core.ITypeHierarchy; 50 import org.eclipse.jdt.core.JavaModelException; 51 import org.eclipse.jdt.core.dom.AST; 52 import org.eclipse.jdt.core.dom.ASTNode; 53 import org.eclipse.jdt.core.dom.ASTVisitor; 54 import org.eclipse.jdt.core.dom.Annotation; 55 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; 56 import org.eclipse.jdt.core.dom.BodyDeclaration; 57 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 58 import org.eclipse.jdt.core.dom.CompilationUnit; 59 import org.eclipse.jdt.core.dom.EnumDeclaration; 60 import org.eclipse.jdt.core.dom.Expression; 61 import org.eclipse.jdt.core.dom.FieldDeclaration; 62 import org.eclipse.jdt.core.dom.IExtendedModifier; 63 import org.eclipse.jdt.core.dom.IMethodBinding; 64 import org.eclipse.jdt.core.dom.ITypeBinding; 65 import org.eclipse.jdt.core.dom.Javadoc; 66 import org.eclipse.jdt.core.dom.MethodDeclaration; 67 import org.eclipse.jdt.core.dom.Modifier; 68 import org.eclipse.jdt.core.dom.Name; 69 import org.eclipse.jdt.core.dom.SimpleName; 70 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 71 import org.eclipse.jdt.core.dom.Type; 72 import org.eclipse.jdt.core.dom.TypeDeclaration; 73 import org.eclipse.jdt.core.dom.TypeParameter; 74 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 75 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 76 import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition; 77 import org.eclipse.jdt.core.search.IJavaSearchConstants; 78 import org.eclipse.jdt.core.search.SearchMatch; 79 import org.eclipse.jdt.core.search.SearchPattern; 80 81 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 82 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 83 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 84 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 85 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; 86 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 87 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 88 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 89 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2; 90 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 91 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; 92 import org.eclipse.jdt.internal.corext.refactoring.reorg.SourceReferenceUtil; 93 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsModel; 94 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeConstraintsSolver; 95 import org.eclipse.jdt.internal.corext.refactoring.structure.constraints.SuperTypeRefactoringProcessor; 96 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 97 import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager; 98 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 99 import org.eclipse.jdt.internal.corext.util.JdtFlags; 100 import org.eclipse.jdt.internal.corext.util.Messages; 101 import org.eclipse.jdt.internal.corext.util.SearchUtils; 102 import org.eclipse.jdt.internal.corext.util.Strings; 103 104 import org.eclipse.jdt.ui.JavaElementLabels; 105 106 import org.eclipse.jdt.internal.ui.JavaPlugin; 107 108 118 public abstract class HierarchyProcessor extends SuperTypeRefactoringProcessor { 119 120 123 public static class TypeVariableMapper extends ASTVisitor { 124 125 126 protected final TypeVariableMaplet[] fMapping; 127 128 129 protected final ASTRewrite fRewrite; 130 131 139 public TypeVariableMapper(final ASTRewrite rewrite, final TypeVariableMaplet[] mapping) { 140 Assert.isNotNull(rewrite); 141 Assert.isNotNull(mapping); 142 fRewrite= rewrite; 143 fMapping= mapping; 144 } 145 146 public final boolean visit(final SimpleName node) { 147 final ITypeBinding binding= node.resolveTypeBinding(); 148 if (binding != null && binding.isTypeVariable()) { 149 String name= null; 150 for (int index= 0; index < fMapping.length; index++) { 151 name= binding.getName(); 152 if (fMapping[index].getSourceName().equals(name) && node.getIdentifier().equals(name)) { 153 final MethodDeclaration declaration= (MethodDeclaration) ASTNodes.getParent(node, MethodDeclaration.class); 154 if (declaration != null) { 155 final IMethodBinding method= declaration.resolveBinding(); 156 if (method != null) { 157 final ITypeBinding[] bindings= method.getTypeParameters(); 158 for (int offset= 0; offset < bindings.length; offset++) { 159 if (bindings[offset].isEqualTo(binding)) 160 return true; 161 } 162 } 163 } 164 fRewrite.set(node, SimpleName.IDENTIFIER_PROPERTY, fMapping[index].getTargetName(), null); 165 } 166 } 167 } 168 return true; 169 } 170 } 171 172 protected static boolean areAllFragmentsDeleted(final FieldDeclaration declaration, final List declarationNodes) { 173 for (final Iterator iterator= declaration.fragments().iterator(); iterator.hasNext();) { 174 if (!declarationNodes.contains(iterator.next())) 175 return false; 176 } 177 return true; 178 } 179 180 protected static RefactoringStatus checkProjectCompliance(CompilationUnitRewrite sourceRewriter, IType destination, IMember[] members) { 181 RefactoringStatus status= new RefactoringStatus(); 182 if (!JavaModelUtil.is50OrHigher(destination.getJavaProject())) { 183 for (int index= 0; index < members.length; index++) { 184 try { 185 BodyDeclaration decl= ASTNodeSearchUtil.getBodyDeclarationNode(members[index], sourceRewriter.getRoot()); 186 if (decl != null) { 187 for (final Iterator iterator= decl.modifiers().iterator(); iterator.hasNext();) { 188 boolean reported= false; 189 final IExtendedModifier modifier= (IExtendedModifier) iterator.next(); 190 if (!reported && modifier.isAnnotation()) { 191 status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_incompatible_langauge_constructs, new String [] { JavaElementLabels.getTextLabel(members[index], JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_DEFAULT)}), JavaStatusContext.create(members[index]))); 192 reported= true; 193 } 194 } 195 } 196 } catch (JavaModelException exception) { 197 JavaPlugin.log(exception); 198 } 199 if (members[index] instanceof IMethod) { 200 final IMethod method= (IMethod) members[index]; 201 try { 202 if (Flags.isVarargs(method.getFlags())) 203 status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.PullUpRefactoring_incompatible_language_constructs1, new String [] { JavaElementLabels.getTextLabel(members[index], JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getTextLabel(destination, JavaElementLabels.ALL_DEFAULT)}), JavaStatusContext.create(members[index]))); 204 } catch (JavaModelException exception) { 205 JavaPlugin.log(exception); 206 } 207 } 208 } 209 } 210 return status; 211 } 212 213 protected static void copyAnnotations(final FieldDeclaration oldField, final FieldDeclaration newField) { 214 final AST ast= newField.getAST(); 215 for (int index= 0, n= oldField.modifiers().size(); index < n; index++) { 216 final IExtendedModifier modifier= (IExtendedModifier) oldField.modifiers().get(index); 217 final List modifiers= newField.modifiers(); 218 if (modifier.isAnnotation() && !modifiers.contains(modifier)) 219 modifiers.add(index, ASTNode.copySubtree(ast, (Annotation) modifier)); 220 } 221 } 222 223 protected static void copyAnnotations(final MethodDeclaration oldMethod, final MethodDeclaration newMethod) { 224 final AST ast= newMethod.getAST(); 225 for (int index= 0, n= oldMethod.modifiers().size(); index < n; index++) { 226 final IExtendedModifier modifier= (IExtendedModifier) oldMethod.modifiers().get(index); 227 final List modifiers= newMethod.modifiers(); 228 if (modifier.isAnnotation() && !modifiers.contains(modifier)) 229 modifiers.add(index, ASTNode.copySubtree(ast, (Annotation) modifier)); 230 } 231 } 232 233 protected static void copyJavadocNode(final ASTRewrite rewrite, final IMember member, final BodyDeclaration oldDeclaration, final BodyDeclaration newDeclaration) throws JavaModelException { 234 final Javadoc predecessor= oldDeclaration.getJavadoc(); 235 if (predecessor != null) { 236 final IDocument buffer= new Document(member.getCompilationUnit().getBuffer().getContents()); 237 try { 238 final String [] lines= Strings.convertIntoLines(buffer.get(predecessor.getStartPosition(), predecessor.getLength())); 239 Strings.trimIndentation(lines, member.getJavaProject(), false); 240 final Javadoc successor= (Javadoc) rewrite.createStringPlaceholder(Strings.concatenate(lines, TextUtilities.getDefaultLineDelimiter(buffer)), ASTNode.JAVADOC); 241 newDeclaration.setJavadoc(successor); 242 } catch (BadLocationException exception) { 243 JavaPlugin.log(exception); 244 } 245 } 246 } 247 248 protected static void copyThrownExceptions(final MethodDeclaration oldMethod, final MethodDeclaration newMethod) { 249 final AST ast= newMethod.getAST(); 250 for (int index= 0, n= oldMethod.thrownExceptions().size(); index < n; index++) 251 newMethod.thrownExceptions().add(index, ASTNode.copySubtree(ast, (Name) oldMethod.thrownExceptions().get(index))); 252 } 253 254 protected static void copyTypeParameters(final MethodDeclaration oldMethod, final MethodDeclaration newMethod) { 255 final AST ast= newMethod.getAST(); 256 for (int index= 0, n= oldMethod.typeParameters().size(); index < n; index++) 257 newMethod.typeParameters().add(index, ASTNode.copySubtree(ast, (TypeParameter) oldMethod.typeParameters().get(index))); 258 } 259 260 protected static String createLabel(final IMember member) { 261 if (member instanceof IType) 262 return JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED); 263 else if (member instanceof IMethod) 264 return JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED); 265 else if (member instanceof IField) 266 return JavaElementLabels.getTextLabel(member, JavaElementLabels.ALL_FULLY_QUALIFIED); 267 else if (member instanceof IInitializer) 268 return RefactoringCoreMessages.HierarchyRefactoring_initializer; 269 Assert.isTrue(false); 270 return null; 271 } 272 273 protected static FieldDeclaration createNewFieldDeclarationNode(final ASTRewrite rewrite, final CompilationUnit unit, final IField field, final VariableDeclarationFragment oldFieldFragment, final TypeVariableMaplet[] mapping, final IProgressMonitor monitor, final RefactoringStatus status, final int modifiers) throws JavaModelException { 274 final VariableDeclarationFragment newFragment= rewrite.getAST().newVariableDeclarationFragment(); 275 newFragment.setExtraDimensions(oldFieldFragment.getExtraDimensions()); 276 if (oldFieldFragment.getInitializer() != null) { 277 Expression newInitializer= null; 278 if (mapping.length > 0) 279 newInitializer= createPlaceholderForExpression(oldFieldFragment.getInitializer(), field.getCompilationUnit(), mapping, rewrite); 280 else 281 newInitializer= createPlaceholderForExpression(oldFieldFragment.getInitializer(), field.getCompilationUnit(), rewrite); 282 newFragment.setInitializer(newInitializer); 283 } 284 newFragment.setName(((SimpleName) ASTNode.copySubtree(rewrite.getAST(), oldFieldFragment.getName()))); 285 final FieldDeclaration newField= rewrite.getAST().newFieldDeclaration(newFragment); 286 final FieldDeclaration oldField= ASTNodeSearchUtil.getFieldDeclarationNode(field, unit); 287 copyJavadocNode(rewrite, field, oldField, newField); 288 copyAnnotations(oldField, newField); 289 newField.modifiers().addAll(ASTNodeFactory.newModifiers(rewrite.getAST(), modifiers)); 290 final Type oldType= oldField.getType(); 291 Type newType= null; 292 if (mapping.length > 0) { 293 newType= createPlaceholderForType(oldType, field.getCompilationUnit(), mapping, rewrite); 294 } else 295 newType= createPlaceholderForType(oldType, field.getCompilationUnit(), rewrite); 296 newField.setType(newType); 297 return newField; 298 } 299 300 protected static Expression createPlaceholderForExpression(final Expression expression, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException { 301 return (Expression) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(expression.getStartPosition(), expression.getLength()), ASTNode.METHOD_INVOCATION); 302 } 303 304 protected static Expression createPlaceholderForExpression(final Expression expression, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException { 305 Expression result= null; 306 try { 307 final IDocument document= new Document(declaringCu.getBuffer().getContents()); 308 final ASTRewrite rewriter= ASTRewrite.create(expression.getAST()); 309 final ITrackedNodePosition position= rewriter.track(expression); 310 expression.accept(new TypeVariableMapper(rewriter, mapping)); 311 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 312 result= (Expression) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.METHOD_INVOCATION); 313 } catch (MalformedTreeException exception) { 314 JavaPlugin.log(exception); 315 } catch (BadLocationException exception) { 316 JavaPlugin.log(exception); 317 } 318 return result; 319 } 320 321 protected static BodyDeclaration createPlaceholderForProtectedTypeDeclaration(final BodyDeclaration bodyDeclaration, final CompilationUnit declaringCuNode, final ICompilationUnit declaringCu, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException { 322 String text= null; 323 try { 324 final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST()); 325 ModifierRewrite.create(rewriter, bodyDeclaration).setVisibility(Modifier.PROTECTED, null); 326 final ITrackedNodePosition position= rewriter.track(bodyDeclaration); 327 final IDocument document= new Document(declaringCu.getBuffer().getText(declaringCuNode.getStartPosition(), declaringCuNode.getLength())); 328 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.UPDATE_REGIONS); 329 text= document.get(position.getStartPosition(), position.getLength()); 330 } catch (BadLocationException exception) { 331 text= getNewText(bodyDeclaration, declaringCu, removeIndentation); 332 } 333 return (BodyDeclaration) rewrite.createStringPlaceholder(text, ASTNode.TYPE_DECLARATION); 334 } 335 336 protected static BodyDeclaration createPlaceholderForProtectedTypeDeclaration(final BodyDeclaration bodyDeclaration, final CompilationUnit declaringCuNode, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException { 337 BodyDeclaration result= null; 338 try { 339 final IDocument document= new Document(declaringCu.getBuffer().getContents()); 340 final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST()); 341 final ITrackedNodePosition position= rewriter.track(bodyDeclaration); 342 bodyDeclaration.accept(new TypeVariableMapper(rewriter, mapping) { 343 344 public final boolean visit(final AnnotationTypeDeclaration node) { 345 ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null); 346 return true; 347 } 348 349 public final boolean visit(final EnumDeclaration node) { 350 ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null); 351 return true; 352 } 353 354 public final boolean visit(final TypeDeclaration node) { 355 ModifierRewrite.create(fRewrite, bodyDeclaration).setVisibility(Modifier.PROTECTED, null); 356 return true; 357 } 358 }); 359 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 360 result= (BodyDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.TYPE_DECLARATION); 361 } catch (MalformedTreeException exception) { 362 JavaPlugin.log(exception); 363 } catch (BadLocationException exception) { 364 JavaPlugin.log(exception); 365 } 366 return result; 367 } 368 369 protected static SingleVariableDeclaration createPlaceholderForSingleVariableDeclaration(final SingleVariableDeclaration declaration, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException { 370 return (SingleVariableDeclaration) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(declaration.getStartPosition(), declaration.getLength()), ASTNode.SINGLE_VARIABLE_DECLARATION); 371 } 372 373 protected static SingleVariableDeclaration createPlaceholderForSingleVariableDeclaration(final SingleVariableDeclaration declaration, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException { 374 SingleVariableDeclaration result= null; 375 try { 376 final IDocument document= new Document(declaringCu.getBuffer().getContents()); 377 final ASTRewrite rewriter= ASTRewrite.create(declaration.getAST()); 378 final ITrackedNodePosition position= rewriter.track(declaration); 379 declaration.accept(new TypeVariableMapper(rewriter, mapping)); 380 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 381 result= (SingleVariableDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.SINGLE_VARIABLE_DECLARATION); 382 } catch (MalformedTreeException exception) { 383 JavaPlugin.log(exception); 384 } catch (BadLocationException exception) { 385 JavaPlugin.log(exception); 386 } 387 return result; 388 } 389 390 protected static Type createPlaceholderForType(final Type type, final ICompilationUnit declaringCu, final ASTRewrite rewrite) throws JavaModelException { 391 return (Type) rewrite.createStringPlaceholder(declaringCu.getBuffer().getText(type.getStartPosition(), type.getLength()), ASTNode.SIMPLE_TYPE); 392 } 393 394 protected static Type createPlaceholderForType(final Type type, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite) throws JavaModelException { 395 Type result= null; 396 try { 397 final IDocument document= new Document(declaringCu.getBuffer().getContents()); 398 final ASTRewrite rewriter= ASTRewrite.create(type.getAST()); 399 final ITrackedNodePosition position= rewriter.track(type); 400 type.accept(new TypeVariableMapper(rewriter, mapping)); 401 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 402 result= (Type) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.SIMPLE_TYPE); 403 } catch (MalformedTreeException exception) { 404 JavaPlugin.log(exception); 405 } catch (BadLocationException exception) { 406 JavaPlugin.log(exception); 407 } 408 return result; 409 } 410 411 protected static BodyDeclaration createPlaceholderForTypeDeclaration(final BodyDeclaration bodyDeclaration, final ICompilationUnit declaringCu, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException { 412 return (BodyDeclaration) rewrite.createStringPlaceholder(getNewText(bodyDeclaration, declaringCu, removeIndentation), ASTNode.TYPE_DECLARATION); 413 } 414 415 protected static BodyDeclaration createPlaceholderForTypeDeclaration(final BodyDeclaration bodyDeclaration, final ICompilationUnit declaringCu, final TypeVariableMaplet[] mapping, final ASTRewrite rewrite, final boolean removeIndentation) throws JavaModelException { 416 BodyDeclaration result= null; 417 try { 418 final IDocument document= new Document(declaringCu.getBuffer().getContents()); 419 final ASTRewrite rewriter= ASTRewrite.create(bodyDeclaration.getAST()); 420 final ITrackedNodePosition position= rewriter.track(bodyDeclaration); 421 bodyDeclaration.accept(new TypeVariableMapper(rewriter, mapping)); 422 rewriter.rewriteAST(document, declaringCu.getJavaProject().getOptions(true)).apply(document, TextEdit.NONE); 423 result= (BodyDeclaration) rewrite.createStringPlaceholder(document.get(position.getStartPosition(), position.getLength()), ASTNode.TYPE_DECLARATION); 424 } catch (MalformedTreeException exception) { 425 JavaPlugin.log(exception); 426 } catch (BadLocationException exception) { 427 JavaPlugin.log(exception); 428 } 429 return result; 430 } 431 432 protected static void deleteDeclarationNodes(final CompilationUnitRewrite sourceRewriter, final boolean sameCu, final CompilationUnitRewrite unitRewriter, final List members, final GroupCategorySet set) throws JavaModelException { 433 final List declarationNodes= getDeclarationNodes(unitRewriter.getRoot(), members); 434 for (final Iterator iterator= declarationNodes.iterator(); iterator.hasNext();) { 435 final ASTNode node= (ASTNode) iterator.next(); 436 final ASTRewrite rewriter= unitRewriter.getASTRewrite(); 437 final ImportRemover remover= unitRewriter.getImportRemover(); 438 if (node instanceof VariableDeclarationFragment) { 439 if (node.getParent() instanceof FieldDeclaration) { 440 final FieldDeclaration declaration= (FieldDeclaration) node.getParent(); 441 if (areAllFragmentsDeleted(declaration, declarationNodes)) { 442 rewriter.remove(declaration, unitRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member, set)); 443 if (!sameCu) 444 remover.registerRemovedNode(declaration); 445 } else { 446 rewriter.remove(node, unitRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member, set)); 447 if (!sameCu) 448 remover.registerRemovedNode(node); 449 } 450 } 451 } else { 452 rewriter.remove(node, unitRewriter.createCategorizedGroupDescription(RefactoringCoreMessages.HierarchyRefactoring_remove_member, set)); 453 if (!sameCu) 454 remover.registerRemovedNode(node); 455 } 456 } 457 } 458 459 protected static List getDeclarationNodes(final CompilationUnit cuNode, final List members) throws JavaModelException { 460 final List result= new ArrayList (members.size()); 461 for (final Iterator iterator= members.iterator(); iterator.hasNext();) { 462 final IMember member= (IMember) iterator.next(); 463 ASTNode node= null; 464 if (member instanceof IField) { 465 if (Flags.isEnum(member.getFlags())) 466 node= ASTNodeSearchUtil.getEnumConstantDeclaration((IField) member, cuNode); 467 else 468 node= ASTNodeSearchUtil.getFieldDeclarationFragmentNode((IField) member, cuNode); 469 } else if (member instanceof IType) 470 node= ASTNodeSearchUtil.getAbstractTypeDeclarationNode((IType) member, cuNode); 471 else if (member instanceof IMethod) 472 node= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) member, cuNode); 473 if (node != null) 474 result.add(node); 475 } 476 return result; 477 } 478 479 protected static String getNewText(final ASTNode node, final ICompilationUnit declaringCu, final boolean removeIndentation) throws JavaModelException { 480 final String result= declaringCu.getBuffer().getText(node.getStartPosition(), node.getLength()); 481 if (removeIndentation) 482 return getUnindentedText(result, declaringCu); 483 484 return result; 485 } 486 487 protected static String getUnindentedText(final String text, final ICompilationUnit declaringCu) throws JavaModelException { 488 final String [] lines= Strings.convertIntoLines(text); 489 Strings.trimIndentation(lines, declaringCu.getJavaProject(), false); 490 return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(declaringCu)); 491 } 492 493 494 protected IType fCachedDeclaringType; 495 496 497 protected final Map fCachedMembersReferences= new HashMap (2); 498 499 500 protected IType[] fCachedReferencedTypes; 501 502 503 protected TextEditBasedChangeManager fChangeManager; 504 505 506 protected final boolean fLayer; 507 508 509 protected IMember[] fMembersToMove; 510 511 520 protected HierarchyProcessor(final IMember[] members, final CodeGenerationSettings settings, boolean layer) { 521 super(settings); 522 fLayer= layer; 523 if (members != null) { 524 fMembersToMove= (IMember[]) SourceReferenceUtil.sortByOffset(members); 525 if (layer && fMembersToMove.length > 0) { 526 final ICompilationUnit original= fMembersToMove[0].getCompilationUnit(); 527 if (original != null) { 528 try { 529 final ICompilationUnit copy= getSharedWorkingCopy(original.getPrimary(), new NullProgressMonitor()); 530 if (copy != null) { 531 for (int index= 0; index < fMembersToMove.length; index++) { 532 final IJavaElement[] elements= copy.findElements(fMembersToMove[index]); 533 if (elements != null && elements.length > 0 && elements[0] instanceof IMember) { 534 fMembersToMove[index]= (IMember) elements[0]; 535 } 536 } 537 } 538 } catch (JavaModelException exception) { 539 JavaPlugin.log(exception); 540 } 541 } 542 } 543 } 544 } 545 546 protected boolean canBeAccessedFrom(final IMember member, final IType target, final ITypeHierarchy hierarchy) throws JavaModelException { 547 Assert.isTrue(!(member instanceof IInitializer)); 548 return member.exists(); 549 } 550 551 protected RefactoringStatus checkConstructorCalls(final IType type, final IProgressMonitor monitor) throws JavaModelException { 552 try { 553 monitor.beginTask(RefactoringCoreMessages.PullUpRefactoring_checking, 2); 554 final RefactoringStatus result= new RefactoringStatus(); 555 final SearchResultGroup[] groups= ConstructorReferenceFinder.getConstructorReferences(type, fOwner, new SubProgressMonitor(monitor, 1), result); 556 final String message= Messages.format(RefactoringCoreMessages.HierarchyRefactoring_gets_instantiated, new Object [] { JavaElementLabels.getTextLabel(type, JavaElementLabels.ALL_FULLY_QUALIFIED)}); 557 558 ICompilationUnit unit= null; 559 for (int index= 0; index < groups.length; index++) { 560 unit= groups[index].getCompilationUnit(); 561 if (unit != null) { 562 final CompilationUnit cuNode= RefactoringASTParser.parseWithASTProvider(unit, false, new SubProgressMonitor(monitor, 1)); 563 final ASTNode[] references= ASTNodeSearchUtil.getAstNodes(groups[index].getSearchResults(), cuNode); 564 ASTNode node= null; 565 for (int offset= 0; offset < references.length; offset++) { 566 node= references[offset]; 567 if ((node instanceof ClassInstanceCreation) || ConstructorReferenceFinder.isImplicitConstructorReferenceNodeInClassCreations(node)) { 568 final RefactoringStatusContext context= JavaStatusContext.create(unit, node); 569 result.addError(message, context); 570 } 571 } 572 } 573 } 574 return result; 575 } finally { 576 monitor.done(); 577 } 578 } 579 580 protected RefactoringStatus checkDeclaringType(final IProgressMonitor monitor) throws JavaModelException { 581 final IType type= getDeclaringType(); 582 if (type.isEnum()) 583 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_enum_members); 584 if (type.isAnnotation()) 585 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_annotation_members); 586 if (type.isInterface()) 587 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_interface_members); 588 if (type.isBinary()) 589 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_members_of_binary); 590 if (type.isReadOnly()) 591 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.HierarchyRefactoring_members_of_read_only); 592 return new RefactoringStatus(); 593 } 594 595 protected RefactoringStatus checkIfMembersExist() { 596 final RefactoringStatus result= new RefactoringStatus(); 597 IMember member= null; 598 for (int index= 0; index < fMembersToMove.length; index++) { 599 member= fMembersToMove[index]; 600 if (member == null || !member.exists()) 601 result.addFatalError(RefactoringCoreMessages.HierarchyRefactoring_does_not_exist); 602 } 603 return result; 604 } 605 606 protected void clearCaches() { 607 fCachedReferencedTypes= null; 608 } 609 610 protected void copyParameters(final ASTRewrite rewrite, final ICompilationUnit unit, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping) throws JavaModelException { 611 SingleVariableDeclaration newDeclaration= null; 612 for (int index= 0, size= oldMethod.parameters().size(); index < size; index++) { 613 final SingleVariableDeclaration oldDeclaration= (SingleVariableDeclaration) oldMethod.parameters().get(index); 614 if (mapping.length > 0) 615 newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, mapping, rewrite); 616 else 617 newDeclaration= createPlaceholderForSingleVariableDeclaration(oldDeclaration, unit, rewrite); 618 newMethod.parameters().add(index, newDeclaration); 619 } 620 } 621 622 protected void copyReturnType(final ASTRewrite rewrite, final ICompilationUnit unit, final MethodDeclaration oldMethod, final MethodDeclaration newMethod, final TypeVariableMaplet[] mapping) throws JavaModelException { 623 Type newReturnType= null; 624 if (mapping.length > 0) 625 newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, mapping, rewrite); 626 else 627 newReturnType= createPlaceholderForType(oldMethod.getReturnType2(), unit, rewrite); 628 newMethod.setReturnType2(newReturnType); 629 } 630 631 protected SuperTypeConstraintsSolver createContraintSolver(final SuperTypeConstraintsModel model) { 632 return new SuperTypeConstraintsSolver(model); 633 } 634 635 public IType getDeclaringType() { 636 if (fCachedDeclaringType != null) 637 return fCachedDeclaringType; 638 fCachedDeclaringType= RefactoringAvailabilityTester.getTopLevelType(fMembersToMove); 639 if (fCachedDeclaringType == null) 640 fCachedDeclaringType= fMembersToMove[0].getDeclaringType(); 641 return fCachedDeclaringType; 642 } 643 644 public IMember[] getMembersToMove() { 645 return fMembersToMove; 646 } 647 648 protected IType[] getTypesReferencedInMovedMembers(final IProgressMonitor monitor) throws JavaModelException { 649 if (fCachedReferencedTypes == null) { 650 final IType[] types= ReferenceFinderUtil.getTypesReferencedIn(fMembersToMove, fOwner, monitor); 651 final List result= new ArrayList (types.length); 652 final List members= Arrays.asList(fMembersToMove); 653 for (int index= 0; index < types.length; index++) { 654 if (!members.contains(types[index]) && !types[index].equals(getDeclaringType())) 655 result.add(types[index]); 656 } 657 fCachedReferencedTypes= new IType[result.size()]; 658 result.toArray(fCachedReferencedTypes); 659 } 660 return fCachedReferencedTypes; 661 } 662 663 protected boolean hasNonMovedReferences(final IMember member, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException { 664 if (!fCachedMembersReferences.containsKey(member)) { 665 final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(member, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE)); 666 engine.setFiltering(true, true); 667 engine.setStatus(status); 668 engine.setOwner(fOwner); 669 engine.setScope(RefactoringScopeFactory.create(member)); 670 engine.searchPattern(new SubProgressMonitor(monitor, 1)); 671 fCachedMembersReferences.put(member, engine.getResults()); 672 } 673 final SearchResultGroup[] groups= (SearchResultGroup[]) fCachedMembersReferences.get(member); 674 if (groups.length == 0) 675 return false; 676 else if (groups.length > 1) 677 return true; 678 final ICompilationUnit unit= groups[0].getCompilationUnit(); 679 if (!getDeclaringType().getCompilationUnit().equals(unit)) 680 return true; 681 final SearchMatch[] matches= groups[0].getSearchResults(); 682 for (int index= 0; index < matches.length; index++) { 683 if (!isMovedReference(matches[index])) 684 return true; 685 } 686 return false; 687 } 688 689 protected boolean isMovedReference(final SearchMatch match) throws JavaModelException { 690 ISourceRange range= null; 691 for (int index= 0; index < fMembersToMove.length; index++) { 692 range= fMembersToMove[index].getSourceRange(); 693 if (range.getOffset() <= match.getOffset() && range.getOffset() + range.getLength() >= match.getOffset()) 694 return true; 695 } 696 return false; 697 } 698 699 public RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants sharedParticipants) throws CoreException { 700 return new RefactoringParticipant[0]; 701 } 702 703 protected boolean needsVisibilityAdjustment(final IMember member, final boolean references, final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException { 704 if (JdtFlags.isPublic(member) || JdtFlags.isProtected(member)) 705 return false; 706 if (!references) 707 return true; 708 return hasNonMovedReferences(member, monitor, status); 709 } 710 } | Popular Tags |