KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > HierarchyProcessor


1 /*******************************************************************************
2  * Copyright (c) 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
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 /**
109  * Partial implementation of a hierarchy refactoring processor used in pull up,
110  * push down and extract supertype refactorings.
111  * <p>
112  * This processor provides common functionality to move members in a type
113  * hierarchy, and to perform a "Use Supertype" refactoring afterwards.
114  * </p>
115  *
116  * @since 3.2
117  */

118 public abstract class HierarchyProcessor extends SuperTypeRefactoringProcessor {
119
120     /**
121      * AST node visitor which performs the actual mapping.
122      */

123     public static class TypeVariableMapper extends ASTVisitor {
124
125         /** The type variable mapping to use */
126         protected final TypeVariableMaplet[] fMapping;
127
128         /** The AST rewrite to use */
129         protected final ASTRewrite fRewrite;
130
131         /**
132          * Creates a new type variable mapper.
133          *
134          * @param rewrite
135          * The AST rewrite to use
136          * @param mapping
137          * The type variable mapping to use
138          */

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 JavaDoc 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 JavaDoc declarationNodes) {
173         for (final Iterator JavaDoc 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 JavaDoc 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 JavaDoc[] { 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 JavaDoc[] { 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 JavaDoc 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 JavaDoc 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 JavaDoc[] 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 JavaDoc 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 JavaDoc 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 JavaDoc members, final GroupCategorySet set) throws JavaModelException {
433         final List JavaDoc declarationNodes= getDeclarationNodes(unitRewriter.getRoot(), members);
434         for (final Iterator JavaDoc 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 JavaDoc getDeclarationNodes(final CompilationUnit cuNode, final List JavaDoc members) throws JavaModelException {
460         final List JavaDoc result= new ArrayList JavaDoc(members.size());
461         for (final Iterator JavaDoc 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 JavaDoc getNewText(final ASTNode node, final ICompilationUnit declaringCu, final boolean removeIndentation) throws JavaModelException {
480         final String JavaDoc 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 JavaDoc getUnindentedText(final String JavaDoc text, final ICompilationUnit declaringCu) throws JavaModelException {
488         final String JavaDoc[] lines= Strings.convertIntoLines(text);
489         Strings.trimIndentation(lines, declaringCu.getJavaProject(), false);
490         return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(declaringCu));
491     }
492
493     /** The cached declaring type */
494     protected IType fCachedDeclaringType;
495
496     /** The cached member references */
497     protected final Map JavaDoc fCachedMembersReferences= new HashMap JavaDoc(2);
498
499     /** The cached type references */
500     protected IType[] fCachedReferencedTypes;
501
502     /** The text edit based change manager */
503     protected TextEditBasedChangeManager fChangeManager;
504
505     /** Does the refactoring use a working copy layer? */
506     protected final boolean fLayer;
507
508     /** The members to move (may be in working copies) */
509     protected IMember[] fMembersToMove;
510
511     /**
512      * Creates a new hierarchy processor.
513      *
514      * @param members
515      * the members, or <code>null</code> if invoked by scripting
516      * @param layer
517      * <code>true</code> to create a working copy layer,
518      * <code>false</code> otherwise
519      */

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 JavaDoc message= Messages.format(RefactoringCoreMessages.HierarchyRefactoring_gets_instantiated, new Object JavaDoc[] { 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 JavaDoc result= new ArrayList JavaDoc(types.length);
652             final List JavaDoc 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