KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 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.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.LinkedList JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import org.eclipse.text.edits.MultiTextEdit;
24 import org.eclipse.text.edits.RangeMarker;
25 import org.eclipse.text.edits.TextEdit;
26 import org.eclipse.text.edits.TextEditGroup;
27 import org.eclipse.text.edits.TextEditProcessor;
28
29 import org.eclipse.core.runtime.Assert;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.OperationCanceledException;
34 import org.eclipse.core.runtime.Status;
35 import org.eclipse.core.runtime.SubProgressMonitor;
36
37 import org.eclipse.core.resources.IFile;
38
39 import org.eclipse.jface.text.BadLocationException;
40 import org.eclipse.jface.text.Document;
41 import org.eclipse.jface.text.IDocument;
42 import org.eclipse.jface.text.IRegion;
43 import org.eclipse.jface.text.Region;
44 import org.eclipse.jface.text.TextUtilities;
45
46 import org.eclipse.ltk.core.refactoring.Change;
47 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
48 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
49 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
50 import org.eclipse.ltk.core.refactoring.TextChange;
51 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
52 import org.eclipse.ltk.core.refactoring.participants.MoveProcessor;
53 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
54 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
55 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
56
57 import org.eclipse.jdt.core.Flags;
58 import org.eclipse.jdt.core.ICompilationUnit;
59 import org.eclipse.jdt.core.IField;
60 import org.eclipse.jdt.core.IJavaElement;
61 import org.eclipse.jdt.core.IJavaProject;
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.JavaCore;
66 import org.eclipse.jdt.core.JavaModelException;
67 import org.eclipse.jdt.core.dom.AST;
68 import org.eclipse.jdt.core.dom.ASTNode;
69 import org.eclipse.jdt.core.dom.ASTVisitor;
70 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
71 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
72 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
73 import org.eclipse.jdt.core.dom.Assignment;
74 import org.eclipse.jdt.core.dom.Block;
75 import org.eclipse.jdt.core.dom.BodyDeclaration;
76 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
77 import org.eclipse.jdt.core.dom.EnumDeclaration;
78 import org.eclipse.jdt.core.dom.Expression;
79 import org.eclipse.jdt.core.dom.FieldAccess;
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.IVariableBinding;
84 import org.eclipse.jdt.core.dom.Javadoc;
85 import org.eclipse.jdt.core.dom.MethodDeclaration;
86 import org.eclipse.jdt.core.dom.MethodInvocation;
87 import org.eclipse.jdt.core.dom.MethodRef;
88 import org.eclipse.jdt.core.dom.MethodRefParameter;
89 import org.eclipse.jdt.core.dom.Modifier;
90 import org.eclipse.jdt.core.dom.Name;
91 import org.eclipse.jdt.core.dom.NullLiteral;
92 import org.eclipse.jdt.core.dom.PostfixExpression;
93 import org.eclipse.jdt.core.dom.PrefixExpression;
94 import org.eclipse.jdt.core.dom.PrimitiveType;
95 import org.eclipse.jdt.core.dom.QualifiedName;
96 import org.eclipse.jdt.core.dom.SimpleName;
97 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
98 import org.eclipse.jdt.core.dom.SuperFieldAccess;
99 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
100 import org.eclipse.jdt.core.dom.TagElement;
101 import org.eclipse.jdt.core.dom.ThisExpression;
102 import org.eclipse.jdt.core.dom.TypeDeclaration;
103 import org.eclipse.jdt.core.dom.TypeParameter;
104 import org.eclipse.jdt.core.dom.VariableDeclaration;
105 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
106 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
107 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
108 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
109 import org.eclipse.jdt.core.search.IJavaSearchConstants;
110 import org.eclipse.jdt.core.search.SearchMatch;
111 import org.eclipse.jdt.core.search.SearchPattern;
112
113 import org.eclipse.jdt.internal.corext.SourceRange;
114 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
115 import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil;
116 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
117 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
118 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
119 import org.eclipse.jdt.internal.corext.dom.Bindings;
120 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
121 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
122 import org.eclipse.jdt.internal.corext.refactoring.Checks;
123 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
124 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
125 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
126 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
127 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
128 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
129 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
130 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
131 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
132 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
133 import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IVisibilityAdjustment;
134 import org.eclipse.jdt.internal.corext.refactoring.tagging.ICommentProvider;
135 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
136 import org.eclipse.jdt.internal.corext.refactoring.tagging.IScriptableRefactoring;
137 import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
138 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
139 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
140 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
141 import org.eclipse.jdt.internal.corext.util.JdtFlags;
142 import org.eclipse.jdt.internal.corext.util.Messages;
143 import org.eclipse.jdt.internal.corext.util.SearchUtils;
144 import org.eclipse.jdt.internal.corext.util.Strings;
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.viewsupport.BindingLabelProvider;
151
152 /**
153  * Refactoring processor to move instance methods.
154  */

155 public final class MoveInstanceMethodProcessor extends MoveProcessor implements IScriptableRefactoring, IDelegateUpdating, ICommentProvider {
156
157     /**
158      * AST visitor to find references to parameters occurring in anonymous
159      * classes of a method body.
160      */

161     public final class AnonymousClassReferenceFinder extends AstNodeFinder {
162
163         /** The anonymous class nesting counter */
164         protected int fAnonymousClass= 0;
165
166         /** The declaring type of the method declaration */
167         protected final ITypeBinding fDeclaringType;
168
169         /**
170          * Creates a new anonymous class reference finder.
171          *
172          * @param declaration
173          * the method declaration to search for references
174          */

175         public AnonymousClassReferenceFinder(final MethodDeclaration declaration) {
176             fDeclaringType= declaration.resolveBinding().getDeclaringClass();
177         }
178
179         public final void endVisit(final AnonymousClassDeclaration node) {
180             Assert.isNotNull(node);
181             if (fAnonymousClass > 0)
182                 fAnonymousClass--;
183             super.endVisit(node);
184         }
185
186         public final boolean visit(final AnonymousClassDeclaration node) {
187             Assert.isNotNull(node);
188             fAnonymousClass++;
189             return super.visit(node);
190         }
191
192         public final boolean visit(final MethodInvocation node) {
193             Assert.isNotNull(node);
194             if (fAnonymousClass > 0) {
195                 final IMethodBinding binding= node.resolveMethodBinding();
196                 if (binding != null) {
197                     if (node.getExpression() == null && !Modifier.isStatic(binding.getModifiers()))
198                         fResult.add(node.getName());
199                 }
200             }
201             return true;
202         }
203
204         public boolean visit(final SimpleName node) {
205             Assert.isNotNull(node);
206             if (fAnonymousClass > 0) {
207                 if (!(node.getParent() instanceof FieldAccess)) {
208                     final IBinding binding= node.resolveBinding();
209                     if (binding instanceof IVariableBinding) {
210                         final IVariableBinding variable= (IVariableBinding) binding;
211                         final ITypeBinding declaring= variable.getDeclaringClass();
212                         if (declaring != null && Bindings.equals(declaring, fDeclaringType))
213                             fResult.add(node);
214                     }
215                 }
216             }
217             return false;
218         }
219     }
220
221     /**
222      * Partial implementation of an ast node finder.
223      */

224     protected static class AstNodeFinder extends ASTVisitor {
225
226         /** The found ast nodes */
227         protected final Set JavaDoc fResult= new HashSet JavaDoc();
228
229         /** The status of the find operation */
230         protected final RefactoringStatus fStatus= new RefactoringStatus();
231
232         /**
233          * Returns the result set.
234          *
235          * @return the result set
236          */

237         public final Set JavaDoc getResult() {
238             return fResult;
239         }
240
241         /**
242          * Returns the status of the find operation.
243          *
244          * @return the status of the operation
245          */

246         public final RefactoringStatus getStatus() {
247             return fStatus;
248         }
249     }
250
251     class DelegateInstanceMethodCreator extends DelegateMethodCreator {
252
253         private Map JavaDoc fAdjustments;
254
255         private boolean fNeededInsertion;
256
257         private Map JavaDoc fRewrites;
258
259         public DelegateInstanceMethodCreator(Map JavaDoc adjustments, Map JavaDoc rewrites) {
260             super();
261             fAdjustments= adjustments;
262             fRewrites= rewrites;
263         }
264
265         protected ASTNode createBody(BodyDeclaration bd) throws JavaModelException {
266             MethodDeclaration methodDeclaration= (MethodDeclaration) bd;
267             final MethodInvocation invocation= getAst().newMethodInvocation();
268             invocation.setName(getAst().newSimpleName(getNewElementName()));
269             invocation.setExpression(createSimpleTargetAccessExpression(methodDeclaration));
270             fNeededInsertion= createArgumentList(methodDeclaration, invocation.arguments(), new VisibilityAdjustingArgumentFactory(getAst(), fRewrites, fAdjustments));
271             final Block block= getAst().newBlock();
272             block.statements().add(createMethodInvocation(methodDeclaration, invocation));
273             if (!fSourceRewrite.getCu().equals(fTargetType.getCompilationUnit()))
274                 fSourceRewrite.getImportRemover().registerRemovedNode(methodDeclaration.getBody());
275             return block;
276         }
277
278         protected ASTNode createDocReference(final BodyDeclaration declaration) throws JavaModelException {
279             return MoveInstanceMethodProcessor.this.createMethodReference((MethodDeclaration) declaration, getAst());
280         }
281
282         protected boolean getNeededInsertion() {
283             return fNeededInsertion;
284         }
285     }
286
287     /**
288      * AST visitor to find 'this' references to enclosing instances.
289      */

290     public final class EnclosingInstanceReferenceFinder extends AstNodeFinder {
291
292         /** The list of enclosing types */
293         private final List JavaDoc fEnclosingTypes= new ArrayList JavaDoc(3);
294
295         /**
296          * Creates a new enclosing instance reference finder.
297          *
298          * @param binding
299          * the declaring type
300          */

301         public EnclosingInstanceReferenceFinder(final ITypeBinding binding) {
302             Assert.isNotNull(binding);
303             ITypeBinding declaring= binding.getDeclaringClass();
304             while (declaring != null) {
305                 fEnclosingTypes.add(declaring);
306                 declaring= declaring.getDeclaringClass();
307             }
308         }
309
310         public final boolean visit(final SimpleName node) {
311             Assert.isNotNull(node);
312             final IBinding binding= node.resolveBinding();
313             ITypeBinding declaring= null;
314             if (binding instanceof IVariableBinding) {
315                 final IVariableBinding variable= (IVariableBinding) binding;
316                 if (Flags.isStatic(variable.getModifiers()))
317                     return false;
318                 declaring= variable.getDeclaringClass();
319             } else if (binding instanceof IMethodBinding) {
320                 final IMethodBinding method= (IMethodBinding) binding;
321                 if (Flags.isStatic(method.getModifiers()))
322                     return false;
323                 declaring= method.getDeclaringClass();
324             }
325             if (declaring != null) {
326                 ITypeBinding enclosing= null;
327                 for (final Iterator JavaDoc iterator= fEnclosingTypes.iterator(); iterator.hasNext();) {
328                     enclosing= (ITypeBinding) iterator.next();
329                     if (Bindings.equals(enclosing, declaring)) {
330                         fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_refers_enclosing_instances, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
331                         fResult.add(node);
332                         break;
333                     }
334                 }
335             }
336             return false;
337         }
338
339         public final boolean visit(final ThisExpression node) {
340             Assert.isNotNull(node);
341             if (node.getQualifier() != null) {
342                 fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_refers_enclosing_instances, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
343                 fResult.add(node);
344             }
345             return false;
346         }
347     }
348
349     /**
350      * AST visitor to find references to type variables or generic types.
351      */

352     public final class GenericReferenceFinder extends AstNodeFinder {
353
354         /** The type parameter binding keys */
355         protected final Set JavaDoc fBindings= new HashSet JavaDoc();
356
357         /**
358          * Creates a new generic reference finder.
359          *
360          * @param declaration
361          * the method declaration
362          */

363         public GenericReferenceFinder(final MethodDeclaration declaration) {
364             Assert.isNotNull(declaration);
365             ITypeBinding binding= null;
366             TypeParameter parameter= null;
367             for (final Iterator JavaDoc iterator= declaration.typeParameters().iterator(); iterator.hasNext();) {
368                 parameter= (TypeParameter) iterator.next();
369                 binding= parameter.resolveBinding();
370                 if (binding != null)
371                     fBindings.add(binding.getKey());
372             }
373         }
374
375         /*
376          * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleName)
377          */

378         public final boolean visit(final SimpleName node) {
379             Assert.isNotNull(node);
380             final IBinding binding= node.resolveBinding();
381             if (binding instanceof ITypeBinding) {
382                 final ITypeBinding type= (ITypeBinding) binding;
383                 if (!fBindings.contains(type.getKey()) && type.isTypeVariable()) {
384                     fResult.add(node);
385                     fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_type_variables, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
386                     return false;
387                 }
388             }
389             return true;
390         }
391     }
392
393     /**
394      * Factory for method argument declaration or expression nodes.
395      */

396     protected static interface IArgumentFactory {
397
398         /**
399          * Returns a argument node for the specified variable binding.
400          *
401          * @param binding
402          * the binding to create a argument node for
403          * @param last
404          * <code>true</code> if the argument represented by this
405          * node is the last one in its declaring method
406          * @return the corresponding node
407          * @throws JavaModelException
408          * if an error occurs
409          */

410         public ASTNode getArgumentNode(IVariableBinding binding, boolean last) throws JavaModelException;
411
412         /**
413          * Returns a target node for the current target.
414          *
415          * @return the corresponding node
416          * @throws JavaModelException
417          * if an error occurs
418          */

419         public ASTNode getTargetNode() throws JavaModelException;
420     }
421
422     /**
423      * AST visitor to rewrite the body of the moved method.
424      */

425     public final class MethodBodyRewriter extends ASTVisitor {
426
427         /** The anonymous class nesting counter */
428         protected int fAnonymousClass= 0;
429
430         /** The method declaration to rewrite */
431         protected final MethodDeclaration fDeclaration;
432
433         /** The set of handled method invocations */
434         protected final Set JavaDoc fMethodDeclarations= new HashSet JavaDoc();
435
436         /** The source ast rewrite to use */
437         protected final ASTRewrite fRewrite;
438
439         /** The existing static imports */
440         protected final Set JavaDoc fStaticImports= new HashSet JavaDoc();
441
442         /** The refactoring status */
443         protected final RefactoringStatus fStatus= new RefactoringStatus();
444
445         /** The target compilation unit rewrite to use */
446         protected final CompilationUnitRewrite fTargetRewrite;
447
448         /**
449          * Creates a new method body rewriter.
450          *
451          * @param targetRewrite
452          * the target compilation unit rewrite to use
453          * @param rewrite
454          * the source ast rewrite to use
455          * @param sourceDeclaration
456          * the source method declaration
457          */

458         public MethodBodyRewriter(final CompilationUnitRewrite targetRewrite, final ASTRewrite rewrite, final MethodDeclaration sourceDeclaration) {
459             Assert.isNotNull(targetRewrite);
460             Assert.isNotNull(rewrite);
461             Assert.isNotNull(sourceDeclaration);
462             fTargetRewrite= targetRewrite;
463             fRewrite= rewrite;
464             fDeclaration= sourceDeclaration;
465             fStaticImports.clear();
466             ImportRewriteUtil.collectImports(fMethod.getJavaProject(), sourceDeclaration, new HashSet JavaDoc(), fStaticImports, false);
467         }
468
469         public final void endVisit(final AnonymousClassDeclaration node) {
470             Assert.isNotNull(node);
471             if (fAnonymousClass > 0)
472                 fAnonymousClass--;
473             super.endVisit(node);
474         }
475
476         public final boolean visit(final AnonymousClassDeclaration node) {
477             Assert.isNotNull(node);
478             fAnonymousClass++;
479             return super.visit(node);
480         }
481
482         public final boolean visit(final ClassInstanceCreation node) {
483             Assert.isNotNull(node);
484             if (node.getParent() instanceof ClassInstanceCreation) {
485                 final AnonymousClassDeclaration declaration= node.getAnonymousClassDeclaration();
486                 if (declaration != null)
487                     visit(declaration);
488                 return false;
489             }
490             return super.visit(node);
491         }
492
493         public final boolean visit(final FieldAccess node) {
494             Assert.isNotNull(node);
495             final Expression expression= node.getExpression();
496             final IVariableBinding variable= node.resolveFieldBinding();
497             final AST ast= fRewrite.getAST();
498             if (expression instanceof ThisExpression) {
499                 if (Bindings.equals(fTarget, variable)) {
500                     if (fAnonymousClass > 0) {
501                         final ThisExpression target= ast.newThisExpression();
502                         target.setQualifier(ast.newSimpleName(fTargetType.getElementName()));
503                         fRewrite.replace(node, target, null);
504                     } else
505                         fRewrite.replace(node, ast.newThisExpression(), null);
506                     return false;
507                 }
508             }
509             if (expression instanceof FieldAccess) {
510                 final FieldAccess access= (FieldAccess) expression;
511                 final IBinding binding= access.getName().resolveBinding();
512                 if ((access.getExpression() instanceof ThisExpression) && Bindings.equals(fTarget, binding)) {
513                     fRewrite.replace(node, ast.newSimpleName(node.getName().getIdentifier()), null);
514                     return false;
515                 }
516             } else if (expression != null) {
517                 final IMethodBinding method= fDeclaration.resolveBinding();
518                 if (variable != null && method != null && !JdtFlags.isStatic(variable) && Bindings.equals(method.getDeclaringClass(), variable.getDeclaringClass())) {
519                     fRewrite.replace(expression, ast.newSimpleName(fTargetName), null);
520                     return false;
521                 }
522             }
523             return true;
524         }
525
526         public final void visit(final List JavaDoc nodes) {
527             Assert.isNotNull(nodes);
528             ASTNode node= null;
529             for (final Iterator JavaDoc iterator= nodes.iterator(); iterator.hasNext();) {
530                 node= (ASTNode) iterator.next();
531                 node.accept(this);
532             }
533         }
534
535         public final boolean visit(final MethodInvocation node) {
536             Assert.isNotNull(node);
537             final Expression expression= node.getExpression();
538             final IMethodBinding method= node.resolveMethodBinding();
539             if (method != null) {
540                 final ASTRewrite rewrite= fRewrite;
541                 if (expression == null) {
542                     final AST ast= node.getAST();
543                     if (!JdtFlags.isStatic(method))
544                         rewrite.set(node, MethodInvocation.EXPRESSION_PROPERTY, ast.newSimpleName(fTargetName), null);
545                     else
546                         rewrite.set(node, MethodInvocation.EXPRESSION_PROPERTY, ast.newSimpleType(ast.newSimpleName(fMethod.getDeclaringType().getElementName())), null);
547                     return true;
548                 } else {
549                     if (expression instanceof FieldAccess) {
550                         final FieldAccess access= (FieldAccess) expression;
551                         if (Bindings.equals(access.resolveFieldBinding(), fTarget)) {
552                             rewrite.remove(expression, null);
553                             visit(node.arguments());
554                             return false;
555                         }
556                     } else if (expression instanceof Name) {
557                         final Name name= (Name) expression;
558                         if (Bindings.equals(name.resolveBinding(), fTarget)) {
559                             rewrite.remove(expression, null);
560                             visit(node.arguments());
561                             return false;
562                         }
563                     }
564                 }
565             }
566             return true;
567         }
568
569         public final boolean visit(final QualifiedName node) {
570             Assert.isNotNull(node);
571             IBinding binding= node.resolveBinding();
572             if (binding instanceof ITypeBinding) {
573                 final ITypeBinding type= (ITypeBinding) binding;
574                 if (type.isClass() && type.getDeclaringClass() != null) {
575                     final String JavaDoc name= fTargetRewrite.getImportRewrite().addImport(type);
576                     if (name != null && name.length() > 0) {
577                         fRewrite.replace(node, ASTNodeFactory.newName(node.getAST(), name), null);
578                         return false;
579                     }
580                 }
581             }
582             binding= node.getQualifier().resolveBinding();
583             if (Bindings.equals(binding, fTarget)) {
584                 fRewrite.replace(node, fRewrite.createCopyTarget(node.getName()), null);
585                 return false;
586             }
587             return true;
588         }
589
590         public final boolean visit(final SimpleName node) {
591             Assert.isNotNull(node);
592             final AST ast= node.getAST();
593             final ASTRewrite rewrite= fRewrite;
594             final IBinding binding= node.resolveBinding();
595             if (binding instanceof ITypeBinding) {
596                 final ITypeBinding type= (ITypeBinding) binding;
597                 if (type.isClass() && type.getDeclaringClass() != null) {
598                     final String JavaDoc name= fTargetRewrite.getImportRewrite().addImport(type);
599                     if (name != null && name.length() > 0) {
600                         fRewrite.replace(node, ASTNodeFactory.newName(ast, name), null);
601                         return false;
602                     }
603                 }
604             }
605             if (Bindings.equals(binding, fTarget))
606                 if (fAnonymousClass > 0) {
607                     final ThisExpression target= ast.newThisExpression();
608                     target.setQualifier(ast.newSimpleName(fTargetType.getElementName()));
609                     fRewrite.replace(node, target, null);
610                 } else
611                     rewrite.replace(node, ast.newThisExpression(), null);
612             else if (binding instanceof IVariableBinding) {
613                 final IVariableBinding variable= (IVariableBinding) binding;
614                 final IMethodBinding method= fDeclaration.resolveBinding();
615                 final ITypeBinding declaring= variable.getDeclaringClass();
616                 if (method != null) {
617                     if (Bindings.equals(method.getDeclaringClass(), declaring)) {
618                         if (JdtFlags.isStatic(variable))
619                             rewrite.replace(node, ast.newQualifiedName(ASTNodeFactory.newName(ast, fTargetRewrite.getImportRewrite().addImport(declaring)), ast.newSimpleName(node.getFullyQualifiedName())), null);
620                         else {
621                             final FieldAccess access= ast.newFieldAccess();
622                             access.setExpression(ast.newSimpleName(fTargetName));
623                             access.setName(ast.newSimpleName(node.getFullyQualifiedName()));
624                             rewrite.replace(node, access, null);
625                         }
626                     } else if (!(node.getParent() instanceof QualifiedName) && JdtFlags.isStatic(variable) && !fStaticImports.contains(variable)) {
627                         rewrite.replace(node, ast.newQualifiedName(ASTNodeFactory.newName(ast, fTargetRewrite.getImportRewrite().addImport(declaring)), ast.newSimpleName(node.getFullyQualifiedName())), null);
628                     }
629                 }
630             }
631             return false;
632         }
633
634         public final boolean visit(final ThisExpression node) {
635             Assert.isNotNull(node);
636             fRewrite.replace(node, node.getAST().newSimpleName(fTargetName), null);
637             return false;
638         }
639     }
640
641     /**
642      * AST visitor to find read-only fields of the declaring class of 'this'.
643      */

644     public static class ReadyOnlyFieldFinder extends ASTVisitor {
645
646         /**
647          * Returns the field binding associated with this expression.
648          *
649          * @param expression
650          * the expression to get the field binding for
651          * @return the field binding, if the expression denotes a field access
652          * or a field name, <code>null</code> otherwise
653          */

654         protected static IVariableBinding getFieldBinding(final Expression expression) {
655             Assert.isNotNull(expression);
656             if (expression instanceof FieldAccess)
657                 return (IVariableBinding) ((FieldAccess) expression).getName().resolveBinding();
658             if (expression instanceof Name) {
659                 final IBinding binding= ((Name) expression).resolveBinding();
660                 if (binding instanceof IVariableBinding) {
661                     final IVariableBinding variable= (IVariableBinding) binding;
662                     if (variable.isField())
663                         return variable;
664                 }
665             }
666             return null;
667         }
668
669         /**
670          * Is the specified name a qualified entity, e.g. preceded by 'this',
671          * 'super' or part of a method invocation?
672          *
673          * @param name
674          * the name to check
675          * @return <code>true</code> if this entity is qualified,
676          * <code>false</code> otherwise
677          */

678         protected static boolean isQualifiedEntity(final Name name) {
679             Assert.isNotNull(name);
680             final ASTNode parent= name.getParent();
681             if ((parent instanceof QualifiedName && ((QualifiedName) parent).getName().equals(name)) || (parent instanceof FieldAccess && ((FieldAccess) parent).getName().equals(name)) || (parent instanceof SuperFieldAccess))
682                 return true;
683             else if (parent instanceof MethodInvocation) {
684                 final MethodInvocation invocation= (MethodInvocation) parent;
685                 return invocation.getExpression() != null && invocation.getName().equals(name);
686             }
687             return false;
688         }
689
690         /** The list of found bindings */
691         protected final List JavaDoc fBindings= new LinkedList JavaDoc();
692
693         /** The keys of the found bindings */
694         protected final Set JavaDoc fFound= new HashSet JavaDoc();
695
696         /** The keys of the written bindings */
697         protected final Set JavaDoc fWritten= new HashSet JavaDoc();
698
699         /**
700          * Creates a new read only field finder.
701          *
702          * @param binding
703          * The declaring class of the method declaring to find fields
704          * for
705          */

706         public ReadyOnlyFieldFinder(final ITypeBinding binding) {
707             Assert.isNotNull(binding);
708             final IVariableBinding[] bindings= binding.getDeclaredFields();
709             IVariableBinding variable= null;
710             for (int index= 0; index < bindings.length; index++) {
711                 variable= bindings[index];
712                 if (!variable.isSynthetic() && !fFound.contains(variable.getKey())) {
713                     fFound.add(variable.getKey());
714                     fBindings.add(variable);
715                 }
716             }
717         }
718
719         /**
720          * Returns all fields of the declaring class plus the ones references in
721          * the visited method declaration.
722          *
723          * @return all fields of the declaring class plus the references ones
724          */

725         public final IVariableBinding[] getDeclaredFields() {
726             final IVariableBinding[] result= new IVariableBinding[fBindings.size()];
727             fBindings.toArray(result);
728             return result;
729         }
730
731         /**
732          * Returns all fields of the declaring class which are not written by
733          * the visited method declaration.
734          *
735          * @return all fields which are not written
736          */

737         public final IVariableBinding[] getReadOnlyFields() {
738             IVariableBinding binding= null;
739             final List JavaDoc list= new LinkedList JavaDoc(fBindings);
740             for (final Iterator JavaDoc iterator= list.iterator(); iterator.hasNext();) {
741                 binding= (IVariableBinding) iterator.next();
742                 if (fWritten.contains(binding.getKey()))
743                     iterator.remove();
744             }
745             final IVariableBinding[] result= new IVariableBinding[list.size()];
746             list.toArray(result);
747             return result;
748         }
749
750         public final boolean visit(final Assignment node) {
751             Assert.isNotNull(node);
752             final IVariableBinding binding= getFieldBinding(node.getLeftHandSide());
753             if (binding != null)
754                 fWritten.add(binding.getKey());
755             return true;
756         }
757
758         public final boolean visit(final FieldAccess node) {
759             Assert.isNotNull(node);
760             if (node.getExpression() instanceof ThisExpression) {
761                 final IVariableBinding binding= (IVariableBinding) node.getName().resolveBinding();
762                 if (binding != null) {
763                     final String JavaDoc key= binding.getKey();
764                     if (!fFound.contains(key)) {
765                         fFound.add(key);
766                         fBindings.add(binding);
767                     }
768                 }
769             }
770             return true;
771         }
772
773         public final boolean visit(final PostfixExpression node) {
774             final IVariableBinding binding= getFieldBinding(node.getOperand());
775             if (binding != null)
776                 fWritten.add(binding.getKey());
777             return true;
778         }
779
780         public final boolean visit(final PrefixExpression node) {
781             final IVariableBinding binding= getFieldBinding(node.getOperand());
782             if (binding != null)
783                 fWritten.add(binding.getKey());
784             return false;
785         }
786
787         public final boolean visit(final SimpleName node) {
788             Assert.isNotNull(node);
789             final IBinding binding= node.resolveBinding();
790             if (binding != null)
791                 if (isFieldAccess(node) && !isQualifiedEntity(node)) {
792                     final IVariableBinding variable= (IVariableBinding) binding;
793                     final String JavaDoc key= variable.getKey();
794                     if (!fFound.contains(key)) {
795                         fFound.add(key);
796                         fBindings.add(variable);
797                     }
798                 }
799             return false;
800         }
801     }
802
803     /**
804      * AST visitor to find recursive calls to the method.
805      */

806     public final class RecursiveCallFinder extends AstNodeFinder {
807
808         /** The method binding */
809         protected final IMethodBinding fBinding;
810
811         /**
812          * Creates a new recursive call finder.
813          *
814          * @param declaration
815          * the method declaration
816          */

817         public RecursiveCallFinder(final MethodDeclaration declaration) {
818             Assert.isNotNull(declaration);
819             fBinding= declaration.resolveBinding();
820         }
821
822         public final boolean visit(final MethodInvocation node) {
823             Assert.isNotNull(node);
824             final Expression expression= node.getExpression();
825             final IMethodBinding binding= node.resolveMethodBinding();
826             if (binding == null || (!Modifier.isStatic(binding.getModifiers()) && Bindings.equals(binding, fBinding) && (expression == null || expression instanceof ThisExpression))) {
827                 fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_potentially_recursive, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
828                 fResult.add(node);
829                 return false;
830             }
831             return true;
832         }
833     }
834
835     /**
836      * AST visitor to find 'super' references.
837      */

838     public final class SuperReferenceFinder extends AstNodeFinder {
839
840         public final boolean visit(final AnnotationTypeDeclaration node) {
841             return false;
842         }
843
844         public final boolean visit(final AnonymousClassDeclaration node) {
845             return false;
846         }
847
848         public final boolean visit(final EnumDeclaration node) {
849             return false;
850         }
851
852         public final boolean visit(final SuperFieldAccess node) {
853             Assert.isNotNull(node);
854             fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_uses_super, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
855             fResult.add(node);
856             return false;
857         }
858
859         public final boolean visit(final SuperMethodInvocation node) {
860             Assert.isNotNull(node);
861             fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_uses_super, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
862             fResult.add(node);
863             return false;
864         }
865
866         public final boolean visit(final TypeDeclaration node) {
867             return false;
868         }
869     }
870
871     /**
872      * AST visitor to find references to 'this'.
873      */

874     public final class ThisReferenceFinder extends AstNodeFinder {
875
876         public final boolean visit(final MethodInvocation node) {
877             Assert.isNotNull(node);
878             final IMethodBinding binding= node.resolveMethodBinding();
879             if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null) {
880                 fResult.add(node);
881                 fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_this_reference, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
882             }
883             return true;
884         }
885
886         public final boolean visit(final SimpleName node) {
887             Assert.isNotNull(node);
888             if (isFieldAccess(node) && !isTargetAccess(node)) {
889                 fResult.add(node);
890                 fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_this_reference, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
891             }
892             return false;
893         }
894
895         public final boolean visit(final ThisExpression node) {
896             Assert.isNotNull(node);
897             fResult.add(node);
898             fStatus.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_this_reference, JavaStatusContext.create(fMethod.getCompilationUnit(), node)));
899             return false;
900         }
901     }
902
903     /**
904      * Argument factory which adjusts the visibilities of the argument types.
905      */

906     public class VisibilityAdjustingArgumentFactory implements IArgumentFactory {
907
908         /** The visibility adjustments */
909         private final Map JavaDoc fAdjustments;
910
911         /** The ast to use for new nodes */
912         private final AST fAst;
913
914         /** The compilation unit rewrites */
915         private final Map JavaDoc fRewrites;
916
917         /**
918          * Creates a new visibility adjusting argument factory.
919          *
920          * @param ast
921          * the ast to use for new nodes
922          * @param rewrites
923          * the compilation unit rewrites
924          * @param adjustments
925          * the map of elements to visibility adjustments
926          */

927         public VisibilityAdjustingArgumentFactory(final AST ast, final Map JavaDoc rewrites, final Map JavaDoc adjustments) {
928             Assert.isNotNull(ast);
929             Assert.isNotNull(rewrites);
930             Assert.isNotNull(adjustments);
931             fAst= ast;
932             fRewrites= rewrites;
933             fAdjustments= adjustments;
934         }
935
936         protected final void adjustTypeVisibility(final ITypeBinding binding) throws JavaModelException {
937             Assert.isNotNull(binding);
938             final IJavaElement element= binding.getJavaElement();
939             if (element instanceof IType) {
940                 final IType type= (IType) element;
941                 if (!type.isBinary() && !type.isReadOnly() && !Flags.isPublic(type.getFlags())) {
942                     boolean same= false;
943                     final CompilationUnitRewrite rewrite= getCompilationUnitRewrite(fRewrites, type.getCompilationUnit());
944                     final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, rewrite.getRoot());
945                     if (declaration != null) {
946                         final ITypeBinding declaring= declaration.resolveBinding();
947                         if (declaring != null && Bindings.equals(binding.getPackage(), fTarget.getType().getPackage()))
948                             same= true;
949                         final Modifier.ModifierKeyword keyword= same ? null : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
950                         final String JavaDoc modifier= same ? RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_default : RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_public;
951                         if (MemberVisibilityAdjustor.hasLowerVisibility(binding.getModifiers(), same ? Modifier.NONE : (keyword == null ? Modifier.NONE : keyword.toFlagValue())) && MemberVisibilityAdjustor.needsVisibilityAdjustments(type, keyword, fAdjustments))
952                             fAdjustments.put(type, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(type, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_type_warning, new String JavaDoc[] { BindingLabelProvider.getBindingLabel(declaration.resolveBinding(), JavaElementLabels.ALL_FULLY_QUALIFIED), modifier }), JavaStatusContext.create(type.getCompilationUnit(), declaration))));
953                     }
954                 }
955             }
956         }
957
958         public ASTNode getArgumentNode(final IVariableBinding binding, final boolean last) throws JavaModelException {
959             Assert.isNotNull(binding);
960             adjustTypeVisibility(binding.getType());
961             return fAst.newSimpleName(binding.getName());
962         }
963
964         public ASTNode getTargetNode() throws JavaModelException {
965             return fAst.newThisExpression();
966         }
967     }
968
969     private static final String JavaDoc ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
970

971     private static final String JavaDoc ATTRIBUTE_INLINE= "inline"; //$NON-NLS-1$
972

973     private static final String JavaDoc ATTRIBUTE_REMOVE= "remove"; //$NON-NLS-1$
974

975     private static final String JavaDoc ATTRIBUTE_TARGET_INDEX= "targetIndex"; //$NON-NLS-1$
976

977     private static final String JavaDoc ATTRIBUTE_TARGET_NAME= "targetName"; //$NON-NLS-1$
978

979     private static final String JavaDoc ATTRIBUTE_USE_GETTER= "getter"; //$NON-NLS-1$
980

981     private static final String JavaDoc ATTRIBUTE_USE_SETTER= "setter"; //$NON-NLS-1$
982

983     /** The identifier of this processor */
984     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.moveInstanceMethodProcessor"; //$NON-NLS-1$
985

986     /**
987      * Returns the bindings of the method arguments of the specified
988      * declaration.
989      *
990      * @param declaration
991      * the method declaration
992      * @return the array of method argument variable bindings
993      */

994     protected static IVariableBinding[] getArgumentBindings(final MethodDeclaration declaration) {
995         Assert.isNotNull(declaration);
996         final List JavaDoc parameters= new ArrayList JavaDoc(declaration.parameters().size());
997         VariableDeclaration variable= null;
998         IVariableBinding binding= null;
999         for (final Iterator JavaDoc iterator= declaration.parameters().iterator(); iterator.hasNext();) {
1000            variable= (VariableDeclaration) iterator.next();
1001            binding= variable.resolveBinding();
1002            if (binding == null)
1003                return new IVariableBinding[0];
1004            parameters.add(binding);
1005        }
1006        final IVariableBinding[] result= new IVariableBinding[parameters.size()];
1007        parameters.toArray(result);
1008        return result;
1009    }
1010
1011    /**
1012     * Returns the bindings of the method argument types of the specified
1013     * declaration.
1014     *
1015     * @param declaration
1016     * the method declaration
1017     * @return the array of method argument variable bindings
1018     */

1019    protected static ITypeBinding[] getArgumentTypes(final MethodDeclaration declaration) {
1020        Assert.isNotNull(declaration);
1021        final IVariableBinding[] parameters= getArgumentBindings(declaration);
1022        final List JavaDoc types= new ArrayList JavaDoc(parameters.length);
1023        IVariableBinding binding= null;
1024        ITypeBinding type= null;
1025        for (int index= 0; index < parameters.length; index++) {
1026            binding= parameters[index];
1027            type= binding.getType();
1028            if (type != null)
1029                types.add(type);
1030        }
1031        final ITypeBinding[] result= new ITypeBinding[types.size()];
1032        types.toArray(result);
1033        return result;
1034    }
1035
1036    /**
1037     * Is the specified name a field access?
1038     *
1039     * @param name
1040     * the name to check
1041     * @return <code>true</code> if this name is a field access,
1042     * <code>false</code> otherwise
1043     */

1044    protected static boolean isFieldAccess(final SimpleName name) {
1045        Assert.isNotNull(name);
1046        final IBinding binding= name.resolveBinding();
1047        if (!(binding instanceof IVariableBinding))
1048            return false;
1049        final IVariableBinding variable= (IVariableBinding) binding;
1050        if (!variable.isField())
1051            return false;
1052        if ("length".equals(name.getIdentifier())) { //$NON-NLS-1$
1053
final ASTNode parent= name.getParent();
1054            if (parent instanceof QualifiedName) {
1055                final QualifiedName qualified= (QualifiedName) parent;
1056                final ITypeBinding type= qualified.getQualifier().resolveTypeBinding();
1057                if (type != null && type.isArray())
1058                    return false;
1059            }
1060        }
1061        return !Modifier.isStatic(variable.getModifiers());
1062    }
1063
1064    /** The candidate targets */
1065    private IVariableBinding[] fCandidateTargets= new IVariableBinding[0];
1066
1067    /** The text change manager */
1068    private TextChangeManager fChangeManager= null;
1069
1070    /** The comment */
1071    private String JavaDoc fComment;
1072
1073    /** Should the delegator be deprecated? */
1074    private boolean fDelegateDeprecation= true;
1075
1076    private boolean fDelegatingUpdating;
1077
1078    /** Should the delegator be inlined? */
1079    private boolean fInline= false;
1080
1081    /** The method to move */
1082    private IMethod fMethod;
1083
1084    /** The name of the new method to generate */
1085    private String JavaDoc fMethodName;
1086
1087    /** The possible targets */
1088    private IVariableBinding[] fPossibleTargets= new IVariableBinding[0];
1089
1090    /** Should the delegator be removed after inlining? */
1091    private boolean fRemove= false;
1092
1093    /** The code generation settings to apply */
1094    private CodeGenerationSettings fSettings;
1095
1096    /** The source compilation unit rewrite */
1097    private CompilationUnitRewrite fSourceRewrite;
1098
1099    /** The new target */
1100    private IVariableBinding fTarget= null;
1101
1102    /** The name of the new target */
1103    private String JavaDoc fTargetName;
1104
1105    /** Does the move method need a target node? */
1106    private boolean fTargetNode= true;
1107
1108    /** The target type */
1109    private IType fTargetType= null;
1110
1111    /** Should getter methods be used to resolve visibility issues? */
1112    private boolean fUseGetters= true;
1113
1114    /** Should setter methods be used to resolve visibility issues? */
1115    private boolean fUseSetters= true;
1116
1117    /**
1118     * Creates a new move instance method processor.
1119     *
1120     * @param method
1121     * the method to move, or <code>null</code> if invoked by
1122     * scripting
1123     * @param settings
1124     * the code generation settings to apply, or <code>null</code>
1125     * if invoked by scripting
1126     */

1127    public MoveInstanceMethodProcessor(final IMethod method, final CodeGenerationSettings settings) {
1128        fSettings= settings;
1129        fMethod= method;
1130        if (method != null)
1131            initialize(method);
1132    }
1133
1134    /**
1135     * {@inheritDoc}
1136     */

1137    public boolean canEnableComment() {
1138        return true;
1139    }
1140
1141    /**
1142     * {@inheritDoc}
1143     */

1144    public final boolean canEnableDelegateUpdating() {
1145        return true;
1146    }
1147
1148    /**
1149     * Checks whether a method with the proposed name already exists in the
1150     * target type.
1151     *
1152     * @param monitor
1153     * the progress monitor to display progress
1154     * @param status
1155     * the status of the condition checking
1156     * @throws JavaModelException
1157     * if the declared methods of the target type could not be
1158     * retrieved
1159     */

1160    protected void checkConflictingMethod(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
1161        Assert.isNotNull(monitor);
1162        Assert.isNotNull(status);
1163        final IMethod[] methods= fTargetType.getMethods();
1164        try {
1165            monitor.beginTask("", methods.length); //$NON-NLS-1$
1166
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1167            IMethod method= null;
1168            for (int index= 0; index < methods.length; index++) {
1169                method= methods[index];
1170                if (method.getElementName().equals(fMethodName) && method.getParameterTypes().length == fMethod.getParameterTypes().length - 1)
1171                    status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_method_already_exists, new String JavaDoc[] { fMethodName, fTargetType.getElementName() }), JavaStatusContext.create(method)));
1172                monitor.worked(1);
1173            }
1174            if (fMethodName.equals(fTargetType.getElementName()))
1175                status.merge(RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_method_type_clash, fMethodName), JavaStatusContext.create(fTargetType)));
1176        } finally {
1177            monitor.done();
1178        }
1179    }
1180
1181    /**
1182     * Checks whether the new target name conflicts with an already existing
1183     * method parameter.
1184     *
1185     * @param monitor
1186     * the progress monitor to display progress
1187     * @param status
1188     * the status of the condition checking
1189     * @throws JavaModelException
1190     * if the method declaration of the method to move could not be
1191     * found
1192     */

1193    protected void checkConflictingTarget(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
1194        Assert.isNotNull(monitor);
1195        Assert.isNotNull(status);
1196        final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
1197        VariableDeclaration variable= null;
1198        final List JavaDoc parameters= declaration.parameters();
1199        try {
1200            monitor.beginTask("", parameters.size()); //$NON-NLS-1$
1201
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1202            for (final Iterator JavaDoc iterator= parameters.iterator(); iterator.hasNext();) {
1203                variable= (VariableDeclaration) iterator.next();
1204                if (fTargetName.equals(variable.getName().getIdentifier())) {
1205                    status.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_target_name_already_used, JavaStatusContext.create(fMethod)));
1206                    break;
1207                }
1208                monitor.worked(1);
1209            }
1210        } finally {
1211            monitor.done();
1212        }
1213    }
1214
1215    /*
1216     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,
1217     * org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
1218     */

1219    public final RefactoringStatus checkFinalConditions(final IProgressMonitor monitor, final CheckConditionsContext context) throws CoreException, OperationCanceledException {
1220        Assert.isNotNull(monitor);
1221        Assert.isNotNull(context);
1222        Assert.isNotNull(fTarget);
1223        final RefactoringStatus status= new RefactoringStatus();
1224        fChangeManager= new TextChangeManager();
1225        try {
1226            monitor.beginTask("", 4); //$NON-NLS-1$
1227
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1228            status.merge(Checks.checkIfCuBroken(fMethod));
1229            if (!status.hasError()) {
1230                checkGenericTarget(new SubProgressMonitor(monitor, 1), status);
1231                if (status.isOK()) {
1232                    final IType type= getTargetType();
1233                    if (type != null) {
1234                        if (type.isBinary() || type.isReadOnly() || !fMethod.exists() || fMethod.isBinary() || fMethod.isReadOnly())
1235                            status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_binary, JavaStatusContext.create(fMethod)));
1236                        else {
1237                            status.merge(Checks.checkIfCuBroken(type));
1238                            if (!status.hasError()) {
1239                                if (!type.exists() || type.isBinary() || type.isReadOnly())
1240                                    status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_binary, JavaStatusContext.create(fMethod)));
1241                                checkConflictingTarget(new SubProgressMonitor(monitor, 1), status);
1242                                checkConflictingMethod(new SubProgressMonitor(monitor, 1), status);
1243                                status.merge(Checks.validateModifiesFiles(computeModifiedFiles(fMethod.getCompilationUnit(), type.getCompilationUnit()), null));
1244                                monitor.worked(1);
1245                                if (!status.hasFatalError())
1246                                    fChangeManager= createChangeManager(status, new SubProgressMonitor(monitor, 1));
1247                            }
1248                        }
1249                    } else
1250                        status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_resolved_target, JavaStatusContext.create(fMethod)));
1251                }
1252            }
1253        } finally {
1254            monitor.done();
1255        }
1256        return status;
1257    }
1258
1259    /**
1260     * Checks whether the target is a type variable or a generic type.
1261     *
1262     * @param monitor
1263     * the progress monitor to display progress
1264     * @param status
1265     * the refactoring status
1266     */

1267    protected void checkGenericTarget(final IProgressMonitor monitor, final RefactoringStatus status) {
1268        Assert.isNotNull(monitor);
1269        Assert.isNotNull(status);
1270        try {
1271            monitor.beginTask("", 1); //$NON-NLS-1$
1272
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1273            final ITypeBinding binding= fTarget.getType();
1274            if (binding == null || binding.isTypeVariable())
1275                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_generic_targets, JavaStatusContext.create(fMethod)));
1276        } finally {
1277            monitor.done();
1278        }
1279    }
1280
1281    /**
1282     * Checks whether the method has references to type variables or generic
1283     * types.
1284     *
1285     * @param monitor
1286     * the progress monitor to display progress
1287     * @param declaration
1288     * the method declaration to check for generic types
1289     * @param status
1290     * the status of the condition checking
1291     */

1292    protected void checkGenericTypes(final IProgressMonitor monitor, final MethodDeclaration declaration, final RefactoringStatus status) {
1293        Assert.isNotNull(monitor);
1294        Assert.isNotNull(declaration);
1295        Assert.isNotNull(status);
1296        try {
1297            monitor.beginTask("", 1); //$NON-NLS-1$
1298
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1299            final AstNodeFinder finder= new GenericReferenceFinder(declaration);
1300            declaration.accept(finder);
1301            if (!finder.getStatus().isOK())
1302                status.merge(finder.getStatus());
1303        } finally {
1304            monitor.done();
1305        }
1306    }
1307
1308    /*
1309     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
1310     */

1311    public final RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
1312        Assert.isNotNull(monitor);
1313        final RefactoringStatus status= new RefactoringStatus();
1314        try {
1315            monitor.beginTask("", 4); //$NON-NLS-1$
1316
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1317            status.merge(Checks.checkIfCuBroken(fMethod));
1318            if (!status.hasError()) {
1319                checkMethodDeclaration(new SubProgressMonitor(monitor, 1), status);
1320                if (status.isOK()) {
1321                    final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
1322                    checkGenericTypes(new SubProgressMonitor(monitor, 1), declaration, status);
1323                    checkMethodBody(new SubProgressMonitor(monitor, 1), declaration, status);
1324                    checkPossibleTargets(new SubProgressMonitor(monitor, 1), declaration, status);
1325                }
1326            }
1327        } finally {
1328            monitor.done();
1329        }
1330        return status;
1331    }
1332
1333    /**
1334     * Checks whether the instance method body is compatible with this
1335     * refactoring.
1336     *
1337     * @param monitor
1338     * the progress monitor to display progress
1339     * @param declaration
1340     * the method declaration whose body to check
1341     * @param status
1342     * the status of the condition checking
1343     */

1344    protected void checkMethodBody(final IProgressMonitor monitor, final MethodDeclaration declaration, final RefactoringStatus status) {
1345        Assert.isNotNull(monitor);
1346        Assert.isNotNull(declaration);
1347        Assert.isNotNull(status);
1348        try {
1349            monitor.beginTask("", 3); //$NON-NLS-1$
1350
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1351            AstNodeFinder finder= new SuperReferenceFinder();
1352            declaration.accept(finder);
1353            if (!finder.getStatus().isOK())
1354                status.merge(finder.getStatus());
1355            monitor.worked(1);
1356            finder= null;
1357            final IMethodBinding binding= declaration.resolveBinding();
1358            if (binding != null) {
1359                final ITypeBinding declaring= binding.getDeclaringClass();
1360                if (declaring != null)
1361                    finder= new EnclosingInstanceReferenceFinder(declaring);
1362            }
1363            if (finder != null) {
1364                declaration.accept(finder);
1365                if (!finder.getStatus().isOK())
1366                    status.merge(finder.getStatus());
1367                monitor.worked(1);
1368                finder= new RecursiveCallFinder(declaration);
1369                declaration.accept(finder);
1370                if (!finder.getStatus().isOK())
1371                    status.merge(finder.getStatus());
1372                monitor.worked(1);
1373            }
1374        } finally {
1375            monitor.done();
1376        }
1377    }
1378
1379    /**
1380     * Checks whether the instance method declaration is compatible with this
1381     * refactoring.
1382     *
1383     * @param monitor
1384     * the progress monitor to display progress
1385     * @param status
1386     * the status of the condition checking
1387     * @throws JavaModelException
1388     * if the method does not exist
1389     */

1390    protected void checkMethodDeclaration(final IProgressMonitor monitor, final RefactoringStatus status) throws JavaModelException {
1391        Assert.isNotNull(monitor);
1392        Assert.isNotNull(status);
1393        try {
1394            monitor.beginTask("", 5); //$NON-NLS-1$
1395
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1396            final int flags= fMethod.getFlags();
1397            if (Flags.isStatic(flags))
1398                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_static_methods, JavaStatusContext.create(fMethod)));
1399            else if (Flags.isAbstract(flags))
1400                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_single_implementation, JavaStatusContext.create(fMethod)));
1401            monitor.worked(1);
1402            if (Flags.isNative(flags))
1403                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_native_methods, JavaStatusContext.create(fMethod)));
1404            monitor.worked(1);
1405            if (Flags.isSynchronized(flags))
1406                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_synchronized_methods, JavaStatusContext.create(fMethod)));
1407            monitor.worked(1);
1408            if (fMethod.isConstructor())
1409                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_constructors, JavaStatusContext.create(fMethod)));
1410            monitor.worked(1);
1411            if (fMethod.getDeclaringType().isAnnotation())
1412                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_annotation, JavaStatusContext.create(fMethod)));
1413            else if (fMethod.getDeclaringType().isInterface())
1414                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_interface, JavaStatusContext.create(fMethod)));
1415            monitor.worked(1);
1416        } finally {
1417            monitor.done();
1418        }
1419    }
1420
1421    /**
1422     * Checks whether the method has possible targets to be moved to
1423     *
1424     * @param monitor
1425     * the progress monitor to display progress
1426     * @param declaration
1427     * the method declaration to check
1428     * @param status
1429     * the status of the condition checking
1430     */

1431    protected void checkPossibleTargets(final IProgressMonitor monitor, final MethodDeclaration declaration, final RefactoringStatus status) {
1432        Assert.isNotNull(monitor);
1433        Assert.isNotNull(declaration);
1434        Assert.isNotNull(status);
1435        try {
1436            monitor.beginTask("", 1); //$NON-NLS-1$
1437
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1438            if (computeTargetCategories(declaration).length < 1)
1439                status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.MoveInstanceMethodProcessor_cannot_be_moved, JavaStatusContext.create(fMethod)));
1440        } finally {
1441            monitor.done();
1442        }
1443    }
1444
1445    /**
1446     * Searches for references to the original method.
1447     *
1448     * @param monitor
1449     * the progress monitor to use
1450     * @param status
1451     * the refactoring status to use
1452     * @return the array of search result groups
1453     * @throws CoreException
1454     * if an error occurred during search
1455     */

1456    protected SearchResultGroup[] computeMethodReferences(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
1457        Assert.isNotNull(monitor);
1458        Assert.isNotNull(status);
1459        try {
1460            monitor.beginTask("", 1); //$NON-NLS-1$
1461
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1462            final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fMethod, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
1463            engine.setStatus(status);
1464            engine.searchPattern(new SubProgressMonitor(monitor, 1));
1465            return (SearchResultGroup[]) engine.getResults();
1466        } finally {
1467            monitor.done();
1468        }
1469    }
1470
1471    /**
1472     * Computes the files that are being modified by this refactoring.
1473     *
1474     * @param source
1475     * the source compilation unit
1476     * @param target
1477     * the target compilation unit
1478     * @return the modified files
1479     */

1480    protected IFile[] computeModifiedFiles(final ICompilationUnit source, final ICompilationUnit target) {
1481        Assert.isNotNull(source);
1482        Assert.isNotNull(target);
1483        if (source.equals(target))
1484            return ResourceUtil.getFiles(new ICompilationUnit[] { source });
1485        return ResourceUtil.getFiles(new ICompilationUnit[] { source, target });
1486    }
1487
1488    /**
1489     * Returns the reserved identifiers in the method to move.
1490     *
1491     * @return the reserved identifiers
1492     * @throws JavaModelException
1493     * if the method declaration could not be found
1494     */

1495    protected String JavaDoc[] computeReservedIdentifiers() throws JavaModelException {
1496        final List JavaDoc names= new ArrayList JavaDoc();
1497        final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
1498        if (declaration != null) {
1499            final List JavaDoc parameters= declaration.parameters();
1500            VariableDeclaration variable= null;
1501            for (int index= 0; index < parameters.size(); index++) {
1502                variable= (VariableDeclaration) parameters.get(index);
1503                names.add(variable.getName().getIdentifier());
1504            }
1505            final Block body= declaration.getBody();
1506            if (body != null) {
1507                final IBinding[] bindings= new ScopeAnalyzer(fSourceRewrite.getRoot()).getDeclarationsAfter(body.getStartPosition(), ScopeAnalyzer.VARIABLES);
1508                for (int index= 0; index < bindings.length; index++)
1509                    names.add(bindings[index].getName());
1510            }
1511        }
1512        final String JavaDoc[] result= new String JavaDoc[names.size()];
1513        names.toArray(result);
1514        return result;
1515    }
1516
1517    /**
1518     * Computes the target categories for the method to move.
1519     *
1520     * @param declaration
1521     * the method declaration
1522     * @return the possible targets as variable bindings of read-only fields and
1523     * parameters
1524     */

1525    protected IVariableBinding[] computeTargetCategories(final MethodDeclaration declaration) {
1526        Assert.isNotNull(declaration);
1527        if (fPossibleTargets.length == 0 || fCandidateTargets.length == 0) {
1528            final List JavaDoc possibleTargets= new ArrayList JavaDoc(16);
1529            final List JavaDoc candidateTargets= new ArrayList JavaDoc(16);
1530            final IMethodBinding method= declaration.resolveBinding();
1531            if (method != null) {
1532                final ITypeBinding declaring= method.getDeclaringClass();
1533                IVariableBinding[] bindings= getArgumentBindings(declaration);
1534                ITypeBinding binding= null;
1535                for (int index= 0; index < bindings.length; index++) {
1536                    binding= bindings[index].getType();
1537                    if ((binding.isClass() || binding.isEnum()) && binding.isFromSource()) {
1538                        possibleTargets.add(bindings[index]);
1539                        candidateTargets.add(bindings[index]);
1540                    }
1541                }
1542                final ReadyOnlyFieldFinder visitor= new ReadyOnlyFieldFinder(declaring);
1543                declaration.accept(visitor);
1544                bindings= visitor.getReadOnlyFields();
1545                for (int index= 0; index < bindings.length; index++) {
1546                    binding= bindings[index].getType();
1547                    if (binding.isClass() && binding.isFromSource())
1548                        possibleTargets.add(bindings[index]);
1549                }
1550                bindings= visitor.getDeclaredFields();
1551                for (int index= 0; index < bindings.length; index++) {
1552                    binding= bindings[index].getType();
1553                    if (binding.isClass() && binding.isFromSource())
1554                        candidateTargets.add(bindings[index]);
1555                }
1556            }
1557            fPossibleTargets= new IVariableBinding[possibleTargets.size()];
1558            possibleTargets.toArray(fPossibleTargets);
1559            fCandidateTargets= new IVariableBinding[candidateTargets.size()];
1560            candidateTargets.toArray(fCandidateTargets);
1561        }
1562        return fPossibleTargets;
1563    }
1564
1565    /**
1566     * Creates a visibility-adjusted target expression taking advantage of
1567     * existing accessor methods.
1568     *
1569     * @param enclosingElement
1570     * the java element which encloses the current method access.
1571     * @param expression
1572     * the expression to access the target, or <code>null</code>
1573     * @param adjustments
1574     * the map of elements to visibility adjustments
1575     * @param rewrite
1576     * the ast rewrite to use
1577     * @return an adjusted target expression, or <code>null</code> if the
1578     * access did not have to be changed
1579     * @throws JavaModelException
1580     * if an error occurs while accessing the target expression
1581     */

1582    protected Expression createAdjustedTargetExpression(final IJavaElement enclosingElement, final Expression expression, final Map JavaDoc adjustments, final ASTRewrite rewrite) throws JavaModelException {
1583        Assert.isNotNull(enclosingElement);
1584        Assert.isNotNull(adjustments);
1585        Assert.isNotNull(rewrite);
1586        final IJavaElement element= fTarget.getJavaElement();
1587        if (element != null && !Modifier.isPublic(fTarget.getModifiers())) {
1588            final IField field= (IField) fTarget.getJavaElement();
1589            if (field != null) {
1590                boolean same= field.getAncestor(IJavaElement.PACKAGE_FRAGMENT).equals(enclosingElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT));
1591                final Modifier.ModifierKeyword keyword= same ? null : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
1592                final String JavaDoc modifier= same ? RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_default : RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_public;
1593                if (fUseGetters) {
1594                    final IMethod getter= GetterSetterUtil.getGetter(field);
1595                    if (getter != null) {
1596                        final MethodDeclaration method= ASTNodeSearchUtil.getMethodDeclarationNode(getter, fSourceRewrite.getRoot());
1597                        if (method != null) {
1598                            final IMethodBinding binding= method.resolveBinding();
1599                            if (binding != null && MemberVisibilityAdjustor.hasLowerVisibility(getter.getFlags(), same ? Modifier.NONE : (keyword == null ? Modifier.NONE : keyword.toFlagValue())) && MemberVisibilityAdjustor.needsVisibilityAdjustments(getter, keyword, adjustments))
1600                                adjustments.put(getter, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(getter, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning, new String JavaDoc[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), modifier }), JavaStatusContext.create(getter))));
1601                            final MethodInvocation invocation= rewrite.getAST().newMethodInvocation();
1602                            invocation.setExpression(expression);
1603                            invocation.setName(rewrite.getAST().newSimpleName(getter.getElementName()));
1604                            return invocation;
1605                        }
1606                    }
1607                }
1608                if (MemberVisibilityAdjustor.hasLowerVisibility(field.getFlags(), (keyword == null ? Modifier.NONE : keyword.toFlagValue())) && MemberVisibilityAdjustor.needsVisibilityAdjustments(field, keyword, adjustments))
1609                    adjustments.put(field, new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(field, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_field_warning, new String JavaDoc[] { BindingLabelProvider.getBindingLabel(fTarget, JavaElementLabels.ALL_FULLY_QUALIFIED), modifier }), JavaStatusContext.create(field))));
1610            }
1611        }
1612        return null;
1613    }
1614
1615    /**
1616     * Creates a generic argument list of the refactored moved method
1617     *
1618     * @param declaration
1619     * the method declaration of the method to move
1620     * @param arguments
1621     * the argument list to create
1622     * @param factory
1623     * the argument factory to use
1624     * @return <code>true</code> if a target node had to be inserted as first
1625     * argument, <code>false</code> otherwise
1626     * @throws JavaModelException
1627     * if an error occurs
1628     */

1629    protected boolean createArgumentList(final MethodDeclaration declaration, final List JavaDoc arguments, final IArgumentFactory factory) throws JavaModelException {
1630        Assert.isNotNull(declaration);
1631        Assert.isNotNull(arguments);
1632        Assert.isNotNull(factory);
1633        final AstNodeFinder finder= new ThisReferenceFinder();
1634        declaration.accept(finder);
1635        IVariableBinding binding= null;
1636        VariableDeclaration variable= null;
1637        boolean added= false;
1638        final int size= declaration.parameters().size();
1639        for (int index= 0; index < size; index++) {
1640            variable= (VariableDeclaration) declaration.parameters().get(index);
1641            binding= variable.resolveBinding();
1642            if (binding != null) {
1643                if (!Bindings.equals(binding, fTarget))
1644                    arguments.add(factory.getArgumentNode(binding, index == size - 1));
1645                else if (!finder.getStatus().isOK()) {
1646                    arguments.add(factory.getTargetNode());
1647                    added= true;
1648                }
1649            } else
1650                arguments.add(factory.getArgumentNode(binding, index == size - 1));
1651        }
1652        if (!finder.getStatus().isOK() && !added) {
1653            arguments.add(0, factory.getTargetNode());
1654            added= true;
1655        }
1656        return added;
1657    }
1658
1659    /*
1660     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor)
1661     */

1662    public final Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException {
1663        Assert.isNotNull(monitor);
1664        try {
1665            monitor.beginTask("", 6); //$NON-NLS-1$
1666
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
1667            final TextChange[] changes= fChangeManager.getAllChanges();
1668            if (changes.length == 1)
1669                return changes[0];
1670            final List JavaDoc list= new ArrayList JavaDoc(changes.length);
1671            list.addAll(Arrays.asList(changes));
1672            final Map JavaDoc arguments= new HashMap JavaDoc();
1673            String JavaDoc project= null;
1674            final IJavaProject javaProject= fMethod.getJavaProject();
1675            if (javaProject != null)
1676                project= javaProject.getElementName();
1677            int flags= JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
1678            final IType declaring= fMethod.getDeclaringType();
1679            try {
1680                if (declaring.isAnonymous() || declaring.isLocal())
1681                    flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1682            } catch (JavaModelException exception) {
1683                JavaPlugin.log(exception);
1684            }
1685            final String JavaDoc description= Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_descriptor_description_short, fMethod.getElementName());
1686            final String JavaDoc header= Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_descriptor_description, new String JavaDoc[] { JavaElementLabels.getElementLabel(fMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(fTarget, JavaElementLabels.ALL_FULLY_QUALIFIED) });
1687            final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
1688            comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_moved_element_pattern, RefactoringCoreMessages.JavaRefactoringDescriptor_not_available));
1689            comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_target_element_pattern, BindingLabelProvider.getBindingLabel(fTarget, JavaElementLabels.ALL_FULLY_QUALIFIED)));
1690            comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_method_name_pattern, getMethodName()));
1691            if (needsTargetNode())
1692                comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_parameter_name_pattern, getTargetName()));
1693            final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.MOVE_METHOD, project, description, comment.asString(), arguments, flags);
1694            arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fMethod));
1695            arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fMethodName);
1696            arguments.put(ATTRIBUTE_TARGET_NAME, fTargetName);
1697            arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString());
1698            arguments.put(ATTRIBUTE_REMOVE, Boolean.valueOf(fRemove).toString());
1699            arguments.put(ATTRIBUTE_INLINE, Boolean.valueOf(fInline).toString());
1700            arguments.put(ATTRIBUTE_USE_GETTER, Boolean.valueOf(fUseGetters).toString());
1701            arguments.put(ATTRIBUTE_USE_SETTER, Boolean.valueOf(fUseSetters).toString());
1702            arguments.put(ATTRIBUTE_TARGET_INDEX, new Integer JavaDoc(getTargetIndex()).toString());
1703            return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.MoveInstanceMethodRefactoring_name, (Change[]) list.toArray(new Change[list.size()]));
1704        } finally {
1705            monitor.done();
1706        }
1707    }
1708
1709    /**
1710     * Creates the text change manager for this processor.
1711     *
1712     * @param status
1713     * the refactoring status
1714     * @param monitor
1715     * the progress monitor to display progress
1716     * @return the created text change manager
1717     * @throws JavaModelException
1718     * if the method declaration could not be found
1719     * @throws CoreException
1720     * if the changes could not be generated
1721     */

1722    protected TextChangeManager createChangeManager(final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException, CoreException {
1723        Assert.isNotNull(status);
1724        Assert.isNotNull(monitor);
1725        try {
1726            monitor.beginTask("", 7); //$NON-NLS-1$
1727
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
1728            fSourceRewrite.clearASTAndImportRewrites();
1729            final TextChangeManager manager= new TextChangeManager();
1730            final CompilationUnitRewrite targetRewrite= fMethod.getCompilationUnit().equals(getTargetType().getCompilationUnit()) ? fSourceRewrite : new CompilationUnitRewrite(getTargetType().getCompilationUnit());
1731            final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
1732            final SearchResultGroup[] references= computeMethodReferences(new SubProgressMonitor(monitor, 1), status);
1733            final Map JavaDoc rewrites= new HashMap JavaDoc(2);
1734            rewrites.put(fSourceRewrite.getCu(), fSourceRewrite);
1735            if (!fSourceRewrite.getCu().equals(targetRewrite.getCu()))
1736                rewrites.put(targetRewrite.getCu(), targetRewrite);
1737            final ASTRewrite sourceRewrite= ASTRewrite.create(fSourceRewrite.getRoot().getAST());
1738            final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fTargetType, fMethod);
1739            adjustor.setStatus(status);
1740            adjustor.setVisibilitySeverity(RefactoringStatus.WARNING);
1741            adjustor.setFailureSeverity(RefactoringStatus.WARNING);
1742            adjustor.setRewrites(rewrites);
1743            adjustor.setRewrite(sourceRewrite, fSourceRewrite.getRoot());
1744            adjustor.adjustVisibility(new SubProgressMonitor(monitor, 1));
1745            final IDocument document= new Document(fMethod.getCompilationUnit().getBuffer().getContents());
1746            final boolean target= createMethodCopy(document, declaration, sourceRewrite, rewrites, adjustor.getAdjustments(), status, new SubProgressMonitor(monitor, 1));
1747            createMethodJavadocReferences(rewrites, declaration, references, target, status, new SubProgressMonitor(monitor, 1));
1748            if (!fSourceRewrite.getCu().equals(targetRewrite.getCu()))
1749                createMethodImports(targetRewrite, declaration, new SubProgressMonitor(monitor, 1), status);
1750            boolean removable= false;
1751            if (fInline) {
1752                removable= createMethodDelegator(rewrites, declaration, references, adjustor.getAdjustments(), target, status, new SubProgressMonitor(monitor, 1));
1753                if (fRemove && removable) {
1754                    fSourceRewrite.getASTRewrite().remove(declaration, fSourceRewrite.createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_remove_original_method));
1755                    if (!fSourceRewrite.getCu().equals(fTargetType.getCompilationUnit()))
1756                        fSourceRewrite.getImportRemover().registerRemovedNode(declaration);
1757                }
1758            }
1759            if (!fRemove || !removable)
1760                createMethodDelegation(declaration, rewrites, adjustor.getAdjustments(), status, new SubProgressMonitor(monitor, 1));
1761
1762            // Do not adjust visibility of a target field; references to the
1763
// field will be removed anyway.
1764
final IJavaElement targetElement= fTarget.getJavaElement();
1765            if (targetElement != null && targetElement instanceof IField && (Flags.isPrivate(fMethod.getFlags()) || !fInline)) {
1766                final IVisibilityAdjustment adjustmentForTarget= (IVisibilityAdjustment) adjustor.getAdjustments().get(targetElement);
1767                if (adjustmentForTarget != null)
1768                    adjustor.getAdjustments().remove(targetElement);
1769            }
1770
1771            adjustor.rewriteVisibility(new SubProgressMonitor(monitor, 1));
1772            sourceRewrite.rewriteAST(document, fMethod.getJavaProject().getOptions(true));
1773            createMethodSignature(document, declaration, sourceRewrite, rewrites);
1774            ICompilationUnit unit= null;
1775            CompilationUnitRewrite rewrite= null;
1776            for (final Iterator JavaDoc iterator= rewrites.keySet().iterator(); iterator.hasNext();) {
1777                unit= (ICompilationUnit) iterator.next();
1778                rewrite= (CompilationUnitRewrite) rewrites.get(unit);
1779                manager.manage(unit, rewrite.createChange());
1780            }
1781            return manager;
1782        } finally {
1783            monitor.done();
1784        }
1785    }
1786
1787    /**
1788     * Creates the necessary change to inline a method invocation represented by
1789     * a search match.
1790     *
1791     * @param rewriter
1792     * the current compilation unit rewrite
1793     * @param declaration
1794     * the source method declaration
1795     * @param match
1796     * the search match representing the method invocation
1797     * @param adjustments
1798     * the map of elements to visibility adjustments
1799     * @param target
1800     * <code>true</code> if a target node had to be inserted as
1801     * first argument, <code>false</code> otherwise
1802     * @param status
1803     * the refactoring status
1804     * @return <code>true</code> if the inline change could be performed,
1805     * <code>false</code> otherwise
1806     * @throws JavaModelException
1807     * if a problem occurred while creating the inlined target
1808     * expression for field targets
1809     */

1810    protected boolean createInlinedMethodInvocation(final CompilationUnitRewrite rewriter, final MethodDeclaration declaration, final SearchMatch match, final Map JavaDoc adjustments, final boolean target, final RefactoringStatus status) throws JavaModelException {
1811        Assert.isNotNull(rewriter);
1812        Assert.isNotNull(declaration);
1813        Assert.isNotNull(match);
1814        Assert.isNotNull(adjustments);
1815        Assert.isNotNull(status);
1816        boolean result= true;
1817        final ASTRewrite rewrite= rewriter.getASTRewrite();
1818        final ASTNode node= ASTNodeSearchUtil.findNode(match, rewriter.getRoot());
1819        final TextEditGroup group= rewriter.createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_method_invocation);
1820        if (node instanceof MethodInvocation) {
1821            final MethodInvocation invocation= (MethodInvocation) node;
1822            final ListRewrite list= rewrite.getListRewrite(invocation, MethodInvocation.ARGUMENTS_PROPERTY);
1823            if (fTarget.isField()) {
1824                Expression access= null;
1825                if (invocation.getExpression() != null) {
1826                    access= createInlinedTargetExpression(rewriter, (IJavaElement) match.getElement(), invocation.getExpression(), adjustments, status);
1827                    rewrite.set(invocation, MethodInvocation.EXPRESSION_PROPERTY, access, group);
1828                } else
1829                    rewrite.set(invocation, MethodInvocation.EXPRESSION_PROPERTY, rewrite.getAST().newSimpleName(fTarget.getName()), group);
1830                if (target) {
1831                    if (access == null || !(access instanceof FieldAccess))
1832                        list.insertFirst(rewrite.getAST().newThisExpression(), null);
1833                    else
1834                        list.insertLast(rewrite.createCopyTarget(invocation.getExpression()), null);
1835                }
1836            } else {
1837                final IVariableBinding[] bindings= getArgumentBindings(declaration);
1838                if (bindings.length > 0) {
1839                    int index= 0;
1840                    for (; index < bindings.length; index++)
1841                        if (Bindings.equals(bindings[index], fTarget))
1842                            break;
1843                    if (index < bindings.length && invocation.arguments().size() > index) {
1844                        final Expression argument= (Expression) invocation.arguments().get(index);
1845                        if (argument instanceof NullLiteral) {
1846                            status.merge(RefactoringStatus.createErrorStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_no_null_argument, BindingLabelProvider.getBindingLabel(declaration.resolveBinding(), JavaElementLabels.ALL_FULLY_QUALIFIED)), JavaStatusContext.create(rewriter.getCu(), invocation)));
1847                            result= false;
1848                        } else {
1849                            if (argument instanceof ThisExpression)
1850                                rewrite.remove(invocation.getExpression(), null);
1851                            else
1852                                rewrite.set(invocation, MethodInvocation.EXPRESSION_PROPERTY, rewrite.createCopyTarget(argument), group);
1853                            if (target) {
1854                                if (invocation.getExpression() != null)
1855                                    list.replace(argument, rewrite.createCopyTarget(invocation.getExpression()), group);
1856                                else {
1857                                    final ThisExpression expression= rewrite.getAST().newThisExpression();
1858                                    final AbstractTypeDeclaration member= (AbstractTypeDeclaration) ASTNodes.getParent(invocation, AbstractTypeDeclaration.class);
1859                                    if (member != null) {
1860                                        final ITypeBinding resolved= member.resolveBinding();
1861                                        if (ASTNodes.getParent(invocation, AnonymousClassDeclaration.class) != null || (resolved != null && resolved.isMember())) {
1862                                            final IMethodBinding method= declaration.resolveBinding();
1863                                            if (method != null) {
1864                                                final ITypeBinding declaring= method.getDeclaringClass();
1865                                                if (declaring != null)
1866                                                    expression.setQualifier(rewrite.getAST().newSimpleName(declaring.getName()));
1867                                            }
1868                                        }
1869                                    }
1870                                    list.replace(argument, expression, group);
1871                                }
1872                            } else
1873                                list.remove(argument, group);
1874                        }
1875                    }
1876                }
1877            }
1878            if (result)
1879                rewrite.set(invocation, MethodInvocation.NAME_PROPERTY, rewrite.getAST().newSimpleName(fMethodName), group);
1880        }
1881        return result;
1882    }
1883
1884    /**
1885     * Creates the target field expression for the inline method invocation.
1886     *
1887     * @param rewriter
1888     * the current compilation unit rewrite
1889     * @param enclosingElement
1890     * the enclosing java element of the method invocation.
1891     * @param original
1892     * the original method invocation expression
1893     * @param adjustments
1894     * the map of elements to visibility adjustments
1895     * @param status
1896     * the refactoring status
1897     * @throws JavaModelException
1898     * if a problem occurred while retrieving potential getter
1899     * methods of the target
1900     */

1901    protected Expression createInlinedTargetExpression(final CompilationUnitRewrite rewriter, final IJavaElement enclosingElement, final Expression original, final Map JavaDoc adjustments, final RefactoringStatus status) throws JavaModelException {
1902        Assert.isNotNull(rewriter);
1903        Assert.isNotNull(enclosingElement);
1904        Assert.isNotNull(original);
1905        Assert.isNotNull(adjustments);
1906        Assert.isNotNull(status);
1907        Assert.isTrue(fTarget.isField());
1908        final Expression expression= (Expression) ASTNode.copySubtree(fSourceRewrite.getASTRewrite().getAST(), original);
1909        final Expression result= createAdjustedTargetExpression(enclosingElement, expression, adjustments, fSourceRewrite.getASTRewrite());
1910        if (result == null) {
1911            final FieldAccess access= fSourceRewrite.getASTRewrite().getAST().newFieldAccess();
1912            access.setExpression(expression);
1913            access.setName(fSourceRewrite.getASTRewrite().getAST().newSimpleName(fTarget.getName()));
1914            return access;
1915        }
1916        return result;
1917    }
1918
1919    /**
1920     * Creates the method arguments for the target method declaration.
1921     *
1922     * @param rewrites
1923     * the compilation unit rewrites
1924     * @param rewrite
1925     * the source ast rewrite
1926     * @param declaration
1927     * the source method declaration
1928     * @param adjustments
1929     * the map of elements to visibility adjustments
1930     * @param status
1931     * the refactoring status
1932     * @return <code>true</code> if a target node had to be inserted as method
1933     * argument, <code>false</code> otherwise
1934     * @throws JavaModelException
1935     * if an error occurs while accessing the types of the arguments
1936     */

1937    protected boolean createMethodArguments(final Map JavaDoc rewrites, final ASTRewrite rewrite, final MethodDeclaration declaration, final Map JavaDoc adjustments, final RefactoringStatus status) throws JavaModelException {
1938        Assert.isNotNull(rewrites);
1939        Assert.isNotNull(declaration);
1940        Assert.isNotNull(rewrite);
1941        Assert.isNotNull(adjustments);
1942        Assert.isNotNull(status);
1943        final CompilationUnitRewrite rewriter= getCompilationUnitRewrite(rewrites, getTargetType().getCompilationUnit());
1944        final AST ast= rewriter.getRoot().getAST();
1945        final AstNodeFinder finder= new AnonymousClassReferenceFinder(declaration);
1946        declaration.accept(finder);
1947        final List JavaDoc arguments= new ArrayList JavaDoc(declaration.parameters().size() + 1);
1948        final boolean result= createArgumentList(declaration, arguments, new VisibilityAdjustingArgumentFactory(ast, rewrites, adjustments) {
1949
1950            public final ASTNode getArgumentNode(final IVariableBinding binding, final boolean last) throws JavaModelException {
1951                Assert.isNotNull(binding);
1952                final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration();
1953                final ITypeBinding type= binding.getType();
1954                adjustTypeVisibility(type);
1955                variable.setName(ast.newSimpleName(binding.getName()));
1956                variable.modifiers().addAll(ast.newModifiers(binding.getModifiers()));
1957                final IMethodBinding method= binding.getDeclaringMethod();
1958                if (last && method != null && method.isVarargs()) {
1959                    variable.setVarargs(true);
1960                    String JavaDoc name= null;
1961                    if (type.isArray()) {
1962                        name= type.getElementType().getName();
1963                        if (PrimitiveType.toCode(name) != null)
1964                            variable.setType(ast.newPrimitiveType(PrimitiveType.toCode(name)));
1965                        else
1966                            variable.setType(ast.newSimpleType(ast.newSimpleName(name)));
1967                    } else {
1968                        name= type.getName();
1969                        if (PrimitiveType.toCode(name) != null)
1970                            variable.setType(ast.newPrimitiveType(PrimitiveType.toCode(name)));
1971                        else
1972                            variable.setType(ast.newSimpleType(ast.newSimpleName(name)));
1973                    }
1974                } else
1975                    variable.setType(rewriter.getImportRewrite().addImport(type, ast));
1976                return variable;
1977            }
1978
1979            public final ASTNode getTargetNode() throws JavaModelException {
1980                final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration();
1981                final IMethodBinding method= declaration.resolveBinding();
1982                if (method != null) {
1983                    final ITypeBinding declaring= method.getDeclaringClass();
1984                    if (declaring != null) {
1985                        adjustTypeVisibility(declaring);
1986                        variable.setType(rewriter.getImportRewrite().addImport(declaring, ast));
1987                        variable.setName(ast.newSimpleName(fTargetName));
1988                        if (finder.getResult().size() > 0)
1989                            variable.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
1990                    }
1991                }
1992                return variable;
1993            }
1994        });
1995        final ListRewrite list= rewrite.getListRewrite(declaration, MethodDeclaration.PARAMETERS_PROPERTY);
1996        ASTNode node= null;
1997        for (final Iterator JavaDoc iterator= declaration.parameters().iterator(); iterator.hasNext();) {
1998            node= (ASTNode) iterator.next();
1999            list.remove(node, null);
2000        }
2001        for (final Iterator JavaDoc iterator= arguments.iterator(); iterator.hasNext();) {
2002            node= (ASTNode) iterator.next();
2003            list.insertLast(node, null);
2004        }
2005        return result;
2006    }
2007
2008    /**
2009     * Creates the method body for the target method declaration.
2010     *
2011     * @param rewriter
2012     * the target compilation unit rewrite
2013     * @param rewrite
2014     * the source ast rewrite
2015     * @param declaration
2016     * the source method declaration
2017     */

2018    protected void createMethodBody(final CompilationUnitRewrite rewriter, final ASTRewrite rewrite, final MethodDeclaration declaration) {
2019        Assert.isNotNull(declaration);
2020        declaration.getBody().accept(new MethodBodyRewriter(rewriter, rewrite, declaration));
2021    }
2022
2023    /**
2024     * Creates the method comment for the target method declaration.
2025     *
2026     * @param rewrite
2027     * the source ast rewrite
2028     * @param declaration
2029     * the source method declaration
2030     * @throws JavaModelException
2031     * if the argument references could not be generated
2032     */

2033    protected void createMethodComment(final ASTRewrite rewrite, final MethodDeclaration declaration) throws JavaModelException {
2034        Assert.isNotNull(rewrite);
2035        Assert.isNotNull(declaration);
2036        final Javadoc comment= declaration.getJavadoc();
2037        if (comment != null) {
2038            final List JavaDoc tags= new LinkedList JavaDoc(comment.tags());
2039            final IVariableBinding[] bindings= getArgumentBindings(declaration);
2040            final Map JavaDoc elements= new HashMap JavaDoc(bindings.length);
2041            String JavaDoc name= null;
2042            List JavaDoc fragments= null;
2043            TagElement element= null;
2044            TagElement reference= null;
2045            IVariableBinding binding= null;
2046            for (int index= 0; index < bindings.length; index++) {
2047                binding= bindings[index];
2048                for (final Iterator JavaDoc iterator= comment.tags().iterator(); iterator.hasNext();) {
2049                    element= (TagElement) iterator.next();
2050                    name= element.getTagName();
2051                    fragments= element.fragments();
2052                    if (name != null) {
2053                        if (name.equals(TagElement.TAG_PARAM) && !fragments.isEmpty() && fragments.get(0) instanceof SimpleName) {
2054                            final SimpleName simple= (SimpleName) fragments.get(0);
2055                            if (binding.getName().equals(simple.getIdentifier())) {
2056                                elements.put(binding.getKey(), element);
2057                                tags.remove(element);
2058                            }
2059                        } else if (reference == null)
2060                            reference= element;
2061                    }
2062                }
2063            }
2064            if (bindings.length == 0 && reference == null) {
2065                for (final Iterator JavaDoc iterator= comment.tags().iterator(); iterator.hasNext();) {
2066                    element= (TagElement) iterator.next();
2067                    name= element.getTagName();
2068                    fragments= element.fragments();
2069                    if (name != null && !name.equals(TagElement.TAG_PARAM))
2070                        reference= element;
2071                }
2072            }
2073            final List JavaDoc arguments= new ArrayList JavaDoc(bindings.length + 1);
2074            createArgumentList(declaration, arguments, new IArgumentFactory() {
2075
2076                public final ASTNode getArgumentNode(final IVariableBinding argument, final boolean last) throws JavaModelException {
2077                    Assert.isNotNull(argument);
2078                    if (elements.containsKey(argument.getKey()))
2079                        return rewrite.createCopyTarget((ASTNode) elements.get(argument.getKey()));
2080                    return JavadocUtil.createParamTag(argument.getName(), declaration.getAST(), fMethod.getJavaProject());
2081                }
2082
2083                public final ASTNode getTargetNode() throws JavaModelException {
2084                    return JavadocUtil.createParamTag(fTargetName, declaration.getAST(), fMethod.getJavaProject());
2085                }
2086            });
2087            final ListRewrite rewriter= rewrite.getListRewrite(comment, Javadoc.TAGS_PROPERTY);
2088            ASTNode tag= null;
2089            for (final Iterator JavaDoc iterator= comment.tags().iterator(); iterator.hasNext();) {
2090                tag= (ASTNode) iterator.next();
2091                if (!tags.contains(tag))
2092                    rewriter.remove(tag, null);
2093            }
2094            for (final Iterator JavaDoc iterator= arguments.iterator(); iterator.hasNext();) {
2095                tag= (ASTNode) iterator.next();
2096                if (reference != null)
2097                    rewriter.insertBefore(tag, reference, null);
2098                else
2099                    rewriter.insertLast(tag, null);
2100            }
2101        }
2102    }
2103
2104    /**
2105     * Creates the method content of the moved method.
2106     *
2107     * @param document
2108     * the document representing the source compilation unit
2109     * @param declaration
2110     * the source method declaration
2111     * @param rewrite
2112     * the ast rewrite to use
2113     * @return the string representing the moved method body
2114     * @throws BadLocationException
2115     * if an offset into the document is invalid
2116     */

2117    protected String JavaDoc createMethodContent(final IDocument document, final MethodDeclaration declaration, final ASTRewrite rewrite) throws BadLocationException {
2118        Assert.isNotNull(document);
2119        Assert.isNotNull(declaration);
2120        Assert.isNotNull(rewrite);
2121        final IRegion range= new Region(declaration.getStartPosition(), declaration.getLength());
2122        final RangeMarker marker= new RangeMarker(range.getOffset(), range.getLength());
2123        final IJavaProject project= fMethod.getJavaProject();
2124        final TextEdit[] edits= rewrite.rewriteAST(document, project.getOptions(true)).removeChildren();
2125        for (int index= 0; index < edits.length; index++)
2126            marker.addChild(edits[index]);
2127        final MultiTextEdit result= new MultiTextEdit();
2128        result.addChild(marker);
2129        final TextEditProcessor processor= new TextEditProcessor(document, new MultiTextEdit(0, document.getLength()), TextEdit.UPDATE_REGIONS);
2130        processor.getRoot().addChild(result);
2131        processor.performEdits();
2132        final IRegion region= document.getLineInformation(document.getLineOfOffset(marker.getOffset()));
2133        return Strings.changeIndent(document.get(marker.getOffset(), marker.getLength()), Strings.computeIndentUnits(document.get(region.getOffset(), region.getLength()), project), project, "", TextUtilities.getDefaultLineDelimiter(document)); //$NON-NLS-1$
2134
}
2135
2136    /**
2137     * Creates the necessary changes to create the delegate method with the
2138     * original method body.
2139     *
2140     * @param document
2141     * the buffer containing the source of the source compilation
2142     * unit
2143     * @param declaration
2144     * the method declaration to use as source
2145     * @param rewrite
2146     * the ast rewrite to use for the copy of the method body
2147     * @param rewrites
2148     * the compilation unit rewrites
2149     * @param adjustments
2150     * the map of elements to visibility adjustments
2151     * @param status
2152     * the refactoring status
2153     * @param monitor
2154     * the progress monitor to display progress
2155     * @throws CoreException
2156     * if an error occurs
2157     * @return <code>true</code> if a target node had to be inserted as first
2158     * argument, <code>false</code> otherwise
2159     */

2160    protected boolean createMethodCopy(final IDocument document, final MethodDeclaration declaration, final ASTRewrite rewrite, final Map JavaDoc rewrites, final Map JavaDoc adjustments, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
2161        Assert.isNotNull(document);
2162        Assert.isNotNull(declaration);
2163        Assert.isNotNull(rewrite);
2164        Assert.isNotNull(rewrites);
2165        Assert.isNotNull(adjustments);
2166        Assert.isNotNull(status);
2167        Assert.isNotNull(monitor);
2168        boolean target= false;
2169        final CompilationUnitRewrite rewriter= getCompilationUnitRewrite(rewrites, getTargetType().getCompilationUnit());
2170        try {
2171            rewrite.set(declaration, MethodDeclaration.NAME_PROPERTY, rewrite.getAST().newSimpleName(fMethodName), null);
2172            boolean same= false;
2173            final IMethodBinding binding= declaration.resolveBinding();
2174            if (binding != null) {
2175                final ITypeBinding declaring= binding.getDeclaringClass();
2176                if (declaring != null && Bindings.equals(declaring.getPackage(), fTarget.getType().getPackage()))
2177                    same= true;
2178                final Modifier.ModifierKeyword keyword= same ? null : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
2179                if (MemberVisibilityAdjustor.hasLowerVisibility(binding.getModifiers(), same ? Modifier.NONE : (keyword == null ? Modifier.NONE : keyword.toFlagValue())) && MemberVisibilityAdjustor.needsVisibilityAdjustments(fMethod, keyword, adjustments)) {
2180                    final MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment adjustment= new MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment(fMethod, keyword, RefactoringStatus.createStatus(RefactoringStatus.WARNING, Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning, new String JavaDoc[] { MemberVisibilityAdjustor.getLabel(fMethod), MemberVisibilityAdjustor.getLabel(keyword) }), JavaStatusContext.create(fMethod), null, RefactoringStatusEntry.NO_CODE, null));
2181                    ModifierRewrite.create(rewrite, declaration).setVisibility(keyword == null ? Modifier.NONE : keyword.toFlagValue(), null);
2182                    adjustment.setNeedsRewriting(false);
2183                    adjustments.put(fMethod, adjustment);
2184                }
2185            }
2186            target= createMethodArguments(rewrites, rewrite, declaration, adjustments, status);
2187            createMethodTypeParameters(rewrite, declaration, status);
2188            createMethodComment(rewrite, declaration);
2189            createMethodBody(rewriter, rewrite, declaration);
2190        } finally {
2191            if (fMethod.getCompilationUnit().equals(getTargetType().getCompilationUnit()))
2192                rewriter.clearImportRewrites();
2193        }
2194        return target;
2195    }
2196
2197    /**
2198     * Creates the necessary changes to replace the body of the method
2199     * declaration with an expression to invoke the delegate.
2200     *
2201     * @param declaration
2202     * the method declaration to replace its body
2203     * @param rewrites
2204     * the compilation unit rewrites
2205     * @param adjustments
2206     * the map of elements to visibility adjustments
2207     * @param status
2208     * the refactoring status
2209     * @param monitor
2210     * the progress monitor to display progress
2211     * @throws CoreException
2212     * if the change could not be generated
2213     * @return <code>true</code> if a target node had to be inserted as first
2214     * argument, <code>false</code> otherwise
2215     */

2216    protected boolean createMethodDelegation(final MethodDeclaration declaration, final Map JavaDoc rewrites, final Map JavaDoc adjustments, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException {
2217        Assert.isNotNull(declaration);
2218        Assert.isNotNull(monitor);
2219
2220        final DelegateInstanceMethodCreator creator= new DelegateInstanceMethodCreator(adjustments, rewrites);
2221        creator.setSourceRewrite(fSourceRewrite);
2222        creator.setCopy(false);
2223        creator.setDeclareDeprecated(fDelegateDeprecation);
2224        creator.setDeclaration(declaration);
2225        creator.setNewElementName(fMethodName);
2226        creator.prepareDelegate();
2227        creator.createEdit();
2228
2229        return creator.getNeededInsertion();
2230    }
2231
2232    /**
2233     * Creates the necessary changes to inline the method invocations to the
2234     * original method.
2235     *
2236     * @param rewrites
2237     * the map of compilation units to compilation unit rewrites
2238     * @param declaration
2239     * the source method declaration
2240     * @param groups
2241     * the search result groups representing all references to the
2242     * moved method, including references in comments
2243     * @param adjustments
2244     * the map of elements to visibility adjustments
2245     * @param target
2246     * <code>true</code> if a target node must be inserted as first
2247     * argument, <code>false</code> otherwise
2248     * @param status
2249     * the refactoring status
2250     * @param monitor
2251     * the progress monitor to use
2252     * @return <code>true</code> if all method invocations to the original
2253     * method declaration could be inlined, <code>false</code>
2254     * otherwise
2255     */

2256    protected boolean createMethodDelegator(final Map JavaDoc rewrites, final MethodDeclaration declaration, final SearchResultGroup[] groups, final Map JavaDoc adjustments, final boolean target, final RefactoringStatus status, final IProgressMonitor monitor) {
2257        Assert.isNotNull(rewrites);
2258        Assert.isNotNull(declaration);
2259        Assert.isNotNull(groups);
2260        Assert.isNotNull(adjustments);
2261        Assert.isNotNull(status);
2262        Assert.isNotNull(monitor);
2263        try {
2264            monitor.beginTask("", groups.length); //$NON-NLS-1$
2265
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
2266            try {
2267                boolean result= true;
2268                boolean found= false;
2269                final ITypeHierarchy hierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1));
2270                IType type= null;
2271                IMethod method= null;
2272                IType[] types= hierarchy.getAllSubtypes(fMethod.getDeclaringType());
2273                for (int index= 0; index < types.length && !found; index++) {
2274                    type= types[index];
2275                    method= JavaModelUtil.findMethod(fMethod.getElementName(), fMethod.getParameterTypes(), false, type);
2276                    if (method != null)
2277                        found= true;
2278                }
2279                types= hierarchy.getAllSupertypes(fMethod.getDeclaringType());
2280                for (int index= 0; index < types.length && !found; index++) {
2281                    type= types[index];
2282                    method= JavaModelUtil.findMethod(fMethod.getElementName(), fMethod.getParameterTypes(), false, type);
2283                    if (method != null)
2284                        found= true;
2285                }
2286                if (found) {
2287                    status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_overridden, BindingLabelProvider.getBindingLabel(declaration.resolveBinding(), JavaElementLabels.ALL_FULLY_QUALIFIED)), JavaStatusContext.create(fMethod)));
2288                    result= false;
2289                } else {
2290                    monitor.worked(1);
2291                    SearchMatch[] matches= null;
2292                    IJavaElement element= null;
2293                    ICompilationUnit unit= null;
2294                    CompilationUnitRewrite rewrite= null;
2295                    SearchResultGroup group= null;
2296                    for (int index= 0; index < groups.length; index++) {
2297                        group= groups[index];
2298                        element= JavaCore.create(group.getResource());
2299                        if (element instanceof ICompilationUnit) {
2300                            matches= group.getSearchResults();
2301                            unit= (ICompilationUnit) element;
2302                            rewrite= getCompilationUnitRewrite(rewrites, unit);
2303                            SearchMatch match= null;
2304                            for (int offset= 0; offset < matches.length; offset++) {
2305                                match= matches[offset];
2306                                if (match.getAccuracy() == SearchMatch.A_INACCURATE) {
2307                                    status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_inaccurate, unit.getCorrespondingResource().getName()), JavaStatusContext.create(unit, new SourceRange(match.getOffset(), match.getLength()))));
2308                                    result= false;
2309                                } else if (!createInlinedMethodInvocation(rewrite, declaration, match, adjustments, target, status))
2310                                    result= false;
2311                            }
2312                        } else if (element != null) {
2313                            status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_binary_project, element.getJavaProject().getElementName())));
2314                            result= false;
2315                        } else {
2316                            status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_binary_resource, group.getResource().getName())));
2317                            result= false;
2318                        }
2319                    }
2320                    monitor.worked(1);
2321                }
2322                return result;
2323            } catch (CoreException exception) {
2324                status.merge(RefactoringStatus.create(exception.getStatus()));
2325                return false;
2326            }
2327        } finally {
2328            monitor.done();
2329        }
2330    }
2331
2332    /**
2333     * Creates the necessary imports for the copied method in the target
2334     * compilation unit.
2335     *
2336     * @param rewrite
2337     * the target compilation unit rewrite
2338     * @param declaration
2339     * the source method declaration
2340     * @param monitor
2341     * the progress monitor to use
2342     * @param status
2343     * the refactoring status to use
2344     * @throws CoreException
2345     * if an error occurs
2346     */

2347    protected void createMethodImports(final CompilationUnitRewrite rewrite, final MethodDeclaration declaration, final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException {
2348        Assert.isNotNull(rewrite);
2349        Assert.isNotNull(declaration);
2350        Assert.isNotNull(monitor);
2351        Assert.isNotNull(status);
2352        monitor.beginTask("", 1); //$NON-NLS-1$
2353
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
2354        try {
2355            ImportRewriteUtil.addImports(rewrite, declaration, new HashMap JavaDoc(), new HashMap JavaDoc(), false);
2356        } finally {
2357            monitor.done();
2358        }
2359    }
2360
2361    /**
2362     * Creates the necessary change to updated a comment reference represented
2363     * by a search match.
2364     *
2365     * @param rewrite
2366     * the current compilation unit rewrite
2367     * @param declaration
2368     * the source method declaration
2369     * @param match
2370     * the search match representing the method reference
2371     * @param targetNode
2372     * <code>true</code> if a target node had to be inserted as
2373     * first argument, <code>false</code> otherwise
2374     * @param status
2375     * the refactoring status
2376     */

2377    protected void createMethodJavadocReference(final CompilationUnitRewrite rewrite, final MethodDeclaration declaration, final SearchMatch match, final boolean targetNode, final RefactoringStatus status) {
2378        Assert.isNotNull(rewrite);
2379        Assert.isNotNull(declaration);
2380        Assert.isNotNull(match);
2381        Assert.isNotNull(status);
2382        final ASTNode node= ASTNodeSearchUtil.findNode(match, rewrite.getRoot());
2383        if (node instanceof MethodRef) {
2384            final AST ast= node.getAST();
2385            final MethodRef successor= ast.newMethodRef();
2386
2387            rewrite.getASTRewrite().replace(node, successor, null);
2388        }
2389    }
2390
2391    /**
2392     * Creates the necessary changes to update tag references to the original
2393     * method.
2394     *
2395     * @param rewrites
2396     * the map of compilation units to compilation unit rewrites
2397     * @param declaration
2398     * the source method declaration
2399     * @param groups
2400     * the search result groups representing all references to the
2401     * moved method, including references in comments
2402     * @param target
2403     * <code>true</code> if a target node must be inserted as first
2404     * argument, <code>false</code> otherwise
2405     * @param status
2406     * the refactoring status
2407     * @param monitor
2408     * the progress monitor to use
2409     */

2410    protected void createMethodJavadocReferences(final Map JavaDoc rewrites, final MethodDeclaration declaration, final SearchResultGroup[] groups, final boolean target, final RefactoringStatus status, final IProgressMonitor monitor) {
2411        Assert.isNotNull(rewrites);
2412        Assert.isNotNull(declaration);
2413        Assert.isNotNull(status);
2414        Assert.isNotNull(monitor);
2415        try {
2416            monitor.beginTask("", groups.length); //$NON-NLS-1$
2417
monitor.setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
2418            try {
2419                SearchMatch[] matches= null;
2420                IJavaElement element= null;
2421                ICompilationUnit unit= null;
2422                CompilationUnitRewrite rewrite= null;
2423                SearchResultGroup group= null;
2424                for (int index= 0; index < groups.length; index++) {
2425                    group= groups[index];
2426                    element= JavaCore.create(group.getResource());
2427                    unit= group.getCompilationUnit();
2428                    if (element instanceof ICompilationUnit) {
2429                        matches= group.getSearchResults();
2430                        unit= (ICompilationUnit) element;
2431                        rewrite= getCompilationUnitRewrite(rewrites, unit);
2432                        SearchMatch match= null;
2433                        for (int offset= 0; offset < matches.length; offset++) {
2434                            match= matches[offset];
2435                            if (match.getAccuracy() == SearchMatch.A_INACCURATE) {
2436                                status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_inaccurate, unit.getCorrespondingResource().getName()), JavaStatusContext.create(unit, new SourceRange(match.getOffset(), match.getLength()))));
2437                            } else
2438                                createMethodJavadocReference(rewrite, declaration, match, target, status);
2439                        }
2440                    } else if (element != null) {
2441                        status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_javadoc_binary_project, element.getJavaProject().getElementName())));
2442                    } else {
2443                        status.merge(RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_javadoc_binary_resource, group.getResource().getName())));
2444                    }
2445                    monitor.worked(1);
2446                }
2447            } catch (CoreException exception) {
2448                status.merge(RefactoringStatus.create(exception.getStatus()));
2449            }
2450        } finally {
2451            monitor.done();
2452        }
2453    }
2454
2455    /**
2456     * Creates a comment method reference to the moved method
2457     *
2458     * @param declaration
2459     * the method declaration of the original method
2460     * @param ast
2461     * the ast to create the method reference for
2462     * @return the created link tag to reference the method
2463     * @throws JavaModelException
2464     * if an error occurs
2465     */

2466    protected ASTNode createMethodReference(final MethodDeclaration declaration, final AST ast) throws JavaModelException {
2467        Assert.isNotNull(ast);
2468        Assert.isNotNull(declaration);
2469        final MethodRef reference= ast.newMethodRef();
2470        reference.setName(ast.newSimpleName(fMethodName));
2471        reference.setQualifier(ASTNodeFactory.newName(ast, JavaModelUtil.getFullyQualifiedName(fTargetType)));
2472        createArgumentList(declaration, reference.parameters(), new IArgumentFactory() {
2473
2474            public final ASTNode getArgumentNode(final IVariableBinding binding, final boolean last) {
2475                Assert.isNotNull(binding);
2476                final MethodRefParameter parameter= ast.newMethodRefParameter();
2477                parameter.setType(ASTNodeFactory.newType(ast, binding.getType().getName()));
2478                return parameter;
2479            }
2480
2481            public final ASTNode getTargetNode() {
2482                final MethodRefParameter parameter= ast.newMethodRefParameter();
2483                final IMethodBinding method= declaration.resolveBinding();
2484                if (method != null) {
2485                    final ITypeBinding declaring= method.getDeclaringClass();
2486                    if (declaring != null)
2487                        parameter.setType(ASTNodeFactory.newType(ast, Bindings.getFullyQualifiedName(declaring)));
2488                }
2489                return parameter;
2490            }
2491        });
2492        return reference;
2493    }
2494
2495    /**
2496     * @param document
2497     * the buffer containing the source of the source compilation
2498     * unit
2499     * @param declaration
2500     * the method declaration to use as source
2501     * @param rewrite
2502     * the ast rewrite to use for the copy of the method body
2503     * @param rewrites
2504     * the compilation unit rewrites
2505     * @throws JavaModelException
2506     * if the insertion point cannot be found
2507     */

2508    protected void createMethodSignature(final IDocument document, final MethodDeclaration declaration, final ASTRewrite rewrite, final Map JavaDoc rewrites) throws JavaModelException {
2509        Assert.isNotNull(document);
2510        Assert.isNotNull(declaration);
2511        Assert.isNotNull(rewrite);
2512        Assert.isNotNull(rewrites);
2513        try {
2514            final CompilationUnitRewrite rewriter= getCompilationUnitRewrite(rewrites, getTargetType().getCompilationUnit());
2515            final MethodDeclaration stub= (MethodDeclaration) rewriter.getASTRewrite().createStringPlaceholder(createMethodContent(document, declaration, rewrite), ASTNode.METHOD_DECLARATION);
2516            final AbstractTypeDeclaration type= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(getTargetType(), rewriter.getRoot());
2517            rewriter.getASTRewrite().getListRewrite(type, type.getBodyDeclarationsProperty()).insertAt(stub, ASTNodes.getInsertionIndex(stub, type.bodyDeclarations()), rewriter.createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_add_moved_method));
2518        } catch (BadLocationException exception) {
2519            JavaPlugin.log(exception);
2520        }
2521    }
2522
2523    /**
2524     * Creates the necessary changes to remove method type parameters if they
2525     * match with enclosing type parameters.
2526     *
2527     * @param rewrite
2528     * the ast rewrite to use
2529     * @param declaration
2530     * the method declaration to remove type parameters
2531     * @param status
2532     * the refactoring status
2533     */

2534    protected void createMethodTypeParameters(final ASTRewrite rewrite, final MethodDeclaration declaration, final RefactoringStatus status) {
2535        ITypeBinding binding= fTarget.getType();
2536        if (binding != null && binding.isParameterizedType()) {
2537            final IMethodBinding method= declaration.resolveBinding();
2538            if (method != null) {
2539                final ITypeBinding[] parameters= method.getTypeParameters();
2540                if (parameters.length > 0) {
2541                    final ListRewrite rewriter= rewrite.getListRewrite(declaration, MethodDeclaration.TYPE_PARAMETERS_PROPERTY);
2542                    boolean foundStatic= false;
2543                    while (binding != null && !foundStatic) {
2544                        if (Flags.isStatic(binding.getModifiers()))
2545                            foundStatic= true;
2546                        final ITypeBinding[] bindings= binding.getTypeArguments();
2547                        for (int index= 0; index < bindings.length; index++) {
2548                            for (int offset= 0; offset < parameters.length; offset++) {
2549                                if (parameters[offset].getName().equals(bindings[index].getName())) {
2550                                    rewriter.remove((ASTNode) rewriter.getOriginalList().get(offset), null);
2551                                    status.addWarning(Messages.format(RefactoringCoreMessages.MoveInstanceMethodProcessor_present_type_parameter_warning, new Object JavaDoc[] { parameters[offset].getName(), BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED) }), JavaStatusContext.create(fMethod));
2552                                }
2553                            }
2554                        }
2555                        binding= binding.getDeclaringClass();
2556                    }
2557                }
2558            }
2559        }
2560    }
2561
2562    /**
2563     * Creates the expression to access the new target.
2564     *
2565     * @param declaration
2566     * the method declaration where to access the target
2567     * @return the corresponding expression
2568     */

2569    protected Expression createSimpleTargetAccessExpression(final MethodDeclaration declaration) {
2570        Assert.isNotNull(declaration);
2571        Expression expression= null;
2572        final AST ast= declaration.getAST();
2573        final ITypeBinding type= fTarget.getDeclaringClass();
2574        if (type != null) {
2575            boolean shadows= false;
2576            final IVariableBinding[] bindings= getArgumentBindings(declaration);
2577            IVariableBinding variable= null;
2578            for (int index= 0; index < bindings.length; index++) {
2579                variable= bindings[index];
2580                if (fMethod.getDeclaringType().getField(variable.getName()).exists()) {
2581                    shadows= true;
2582                    break;
2583                }
2584            }
2585            if (fSettings.useKeywordThis || shadows) {
2586                final FieldAccess access= ast.newFieldAccess();
2587                access.setName(ast.newSimpleName(fTarget.getName()));
2588                access.setExpression(ast.newThisExpression());
2589                expression= access;
2590            } else
2591                expression= ast.newSimpleName(fTarget.getName());
2592        } else
2593            expression= ast.newSimpleName(fTarget.getName());
2594        return expression;
2595    }
2596
2597    /**
2598     * Returns the candidate targets for the method to move.
2599     *
2600     * @return the candidate targets as variable bindings of fields and
2601     * parameters
2602     */

2603    public final IVariableBinding[] getCandidateTargets() {
2604        Assert.isNotNull(fCandidateTargets);
2605        return fCandidateTargets;
2606    }
2607
2608    /**
2609     * {@inheritDoc}
2610     */

2611    public String JavaDoc getComment() {
2612        return fComment;
2613    }
2614
2615    /**
2616     * Returns a compilation unit rewrite for the specified compilation unit.
2617     *
2618     * @param rewrites
2619     * the compilation unit rewrite map
2620     * @param unit
2621     * the compilation unit
2622     * @return the corresponding compilation unit rewrite
2623     */

2624    protected CompilationUnitRewrite getCompilationUnitRewrite(final Map JavaDoc rewrites, final ICompilationUnit unit) {
2625        Assert.isNotNull(rewrites);
2626        Assert.isNotNull(unit);
2627        CompilationUnitRewrite rewrite= (CompilationUnitRewrite) rewrites.get(unit);
2628        if (rewrite == null) {
2629            rewrite= new CompilationUnitRewrite(unit);
2630            rewrites.put(unit, rewrite);
2631        }
2632        return rewrite;
2633    }
2634
2635    /**
2636     * {@inheritDoc}
2637     */

2638    public final boolean getDelegateUpdating() {
2639        return fDelegatingUpdating;
2640    }
2641
2642    /**
2643     * {@inheritDoc}
2644     */

2645    public String JavaDoc getDelegateUpdatingTitle(boolean plural) {
2646        if (plural)
2647            return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_plural;
2648        else
2649            return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_singular;
2650    }
2651
2652    /**
2653     * {@inheritDoc}
2654     */

2655    public final boolean getDeprecateDelegates() {
2656        return fDelegateDeprecation;
2657    }
2658
2659    /**
2660     * {@inheritDoc}
2661     */

2662    public final Object JavaDoc[] getElements() {
2663        return new Object JavaDoc[] { fMethod };
2664    }
2665
2666    /**
2667     * {@inheritDoc}
2668     */

2669    public final String JavaDoc getIdentifier() {
2670        return IDENTIFIER;
2671    }
2672
2673    /**
2674     * Returns the method to be moved.
2675     *
2676     * @return the method to be moved
2677     */

2678    public final IMethod getMethod() {
2679        return fMethod;
2680    }
2681
2682    /**
2683     * Returns the new method name.
2684     *
2685     * @return the name of the new method
2686     */

2687    public final String JavaDoc getMethodName() {
2688        return fMethodName;
2689    }
2690
2691    /**
2692     * Returns the possible targets for the method to move.
2693     *
2694     * @return the possible targets as variable bindings of read-only fields and
2695     * parameters
2696     */

2697    public final IVariableBinding[] getPossibleTargets() {
2698        Assert.isNotNull(fPossibleTargets);
2699        return fPossibleTargets;
2700    }
2701
2702    /*
2703     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
2704     */

2705    public final String JavaDoc getProcessorName() {
2706        return RefactoringCoreMessages.MoveInstanceMethodProcessor_name;
2707    }
2708
2709    /**
2710     * Returns the index of the chosen target.
2711     *
2712     * @return the target index
2713     */

2714    protected final int getTargetIndex() {
2715        final IVariableBinding[] targets= getPossibleTargets();
2716        int result= -1;
2717        for (int index= 0; index < targets.length; index++) {
2718            if (Bindings.equals(fTarget, targets[index])) {
2719                result= index;
2720                break;
2721            }
2722        }
2723        return result;
2724    }
2725
2726    /**
2727     * Returns the new target name.
2728     *
2729     * @return the name of the new target
2730     */

2731    public final String JavaDoc getTargetName() {
2732        return fTargetName;
2733    }
2734
2735    /**
2736     * Returns the type of the new target.
2737     *
2738     * @return the type of the new target
2739     * @throws JavaModelException
2740     * if the type does not exist
2741     */

2742    protected IType getTargetType() throws JavaModelException {
2743        Assert.isNotNull(fTarget);
2744        if (fTargetType == null) {
2745            final ITypeBinding binding= fTarget.getType();
2746            if (binding != null)
2747                fTargetType= (IType) binding.getJavaElement();
2748            else
2749                throw new JavaModelException(new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), 0, RefactoringCoreMessages.MoveInstanceMethodProcessor_cannot_be_moved, null)));
2750        }
2751        return fTargetType;
2752    }
2753
2754    /**
2755     * Initializes the refactoring with the given input.
2756     *
2757     * @param method
2758     * the method to move
2759     */

2760    protected void initialize(final IMethod method) {
2761        Assert.isNotNull(method);
2762        fSourceRewrite= new CompilationUnitRewrite(fMethod.getCompilationUnit());
2763        fMethodName= method.getElementName();
2764        fTargetName= suggestTargetName();
2765        if (fSettings == null)
2766            fSettings= JavaPreferencesSettings.getCodeGenerationSettings(fMethod.getJavaProject());
2767    }
2768
2769    /**
2770     * {@inheritDoc}
2771     */

2772    public RefactoringStatus initialize(final RefactoringArguments arguments) {
2773        if (arguments instanceof JavaRefactoringArguments) {
2774            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
2775            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
2776            if (handle != null) {
2777                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
2778                if (element == null || !element.exists() || element.getElementType() != IJavaElement.METHOD)
2779                    return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.MOVE_METHOD);
2780                else {
2781                    fMethod= (IMethod) element;
2782                    initialize(fMethod);
2783                }
2784            } else
2785                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
2786            final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
2787            if (name != null) {
2788                final RefactoringStatus status= setMethodName(name);
2789                if (status.hasError())
2790                    return status;
2791            } else
2792                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
2793            final String JavaDoc deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
2794            if (deprecate != null) {
2795                fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue();
2796            } else
2797                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
2798            final String JavaDoc remove= extended.getAttribute(ATTRIBUTE_REMOVE);
2799            if (remove != null) {
2800                fRemove= Boolean.valueOf(remove).booleanValue();
2801            } else
2802                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REMOVE));
2803            final String JavaDoc inline= extended.getAttribute(ATTRIBUTE_INLINE);
2804            if (inline != null) {
2805                fInline= Boolean.valueOf(inline).booleanValue();
2806            } else
2807                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_INLINE));
2808            final String JavaDoc getter= extended.getAttribute(ATTRIBUTE_USE_GETTER);
2809            if (getter != null)
2810                fUseGetters= Boolean.valueOf(getter).booleanValue();
2811            else
2812                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_USE_GETTER));
2813            final String JavaDoc setter= extended.getAttribute(ATTRIBUTE_USE_SETTER);
2814            if (setter != null)
2815                fUseSetters= Boolean.valueOf(setter).booleanValue();
2816            else
2817                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_USE_SETTER));
2818            final String JavaDoc target= extended.getAttribute(ATTRIBUTE_TARGET_NAME);
2819            if (target != null) {
2820                final RefactoringStatus status= setTargetName(target);
2821                if (status.hasError())
2822                    return status;
2823            } else
2824                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TARGET_NAME));
2825            final String JavaDoc value= extended.getAttribute(ATTRIBUTE_TARGET_INDEX);
2826            if (value != null) {
2827                try {
2828                    final int index= Integer.valueOf(value).intValue();
2829                    if (index >= 0) {
2830                        final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
2831                        if (declaration != null) {
2832                            final IVariableBinding[] bindings= computeTargetCategories(declaration);
2833                            if (bindings != null && index < bindings.length)
2834                                setTarget(bindings[index]);
2835                        }
2836                    }
2837                } catch (NumberFormatException JavaDoc exception) {
2838                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new String JavaDoc[] { value, ATTRIBUTE_TARGET_INDEX }));
2839                } catch (JavaModelException exception) {
2840                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new String JavaDoc[] { value, ATTRIBUTE_TARGET_INDEX }));
2841                }
2842            } else
2843                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TARGET_INDEX));
2844        } else
2845            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
2846        return new RefactoringStatus();
2847    }
2848
2849    /*
2850     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
2851     */

2852    public final boolean isApplicable() throws CoreException {
2853        return fMethod.exists() && !fMethod.isConstructor() && !fMethod.isBinary() && !fMethod.isReadOnly() && fMethod.getCompilationUnit() != null && !JdtFlags.isStatic(fMethod);
2854    }
2855
2856    /**
2857     * Is the specified name a target access?
2858     *
2859     * @param name
2860     * the name to check
2861     * @return <code>true</code> if this name is a target access,
2862     * <code>false</code> otherwise
2863     */

2864    protected boolean isTargetAccess(final Name name) {
2865        Assert.isNotNull(name);
2866        final IBinding binding= name.resolveBinding();
2867        if (Bindings.equals(fTarget, binding))
2868            return true;
2869        if (name.getParent() instanceof FieldAccess) {
2870            final FieldAccess access= (FieldAccess) name.getParent();
2871            final Expression expression= access.getExpression();
2872            if (expression instanceof Name)
2873                return isTargetAccess((Name) expression);
2874        } else if (name instanceof QualifiedName) {
2875            final QualifiedName qualified= (QualifiedName) name;
2876            if (qualified.getQualifier() != null)
2877                return isTargetAccess(qualified.getQualifier());
2878        }
2879        return false;
2880    }
2881
2882    /*
2883     * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,
2884     * org.eclipse.ltk.core.refactoring.participants.SharableParticipants)
2885     */

2886    public final RefactoringParticipant[] loadParticipants(final RefactoringStatus status, final SharableParticipants participants) throws CoreException {
2887        return new RefactoringParticipant[0];
2888    }
2889
2890    /**
2891     * Does the moved method need a target node?
2892     *
2893     * @return <code>true</code> if it needs a target node, <code>false</code>
2894     * otherwise
2895     */

2896    public final boolean needsTargetNode() {
2897        return fTargetNode;
2898    }
2899
2900    /**
2901     * {@inheritDoc}
2902     */

2903    public void setComment(final String JavaDoc comment) {
2904        fComment= comment;
2905    }
2906
2907    /**
2908     * {@inheritDoc}
2909     */

2910    public final void setDelegateUpdating(final boolean updating) {
2911        fDelegatingUpdating= updating;
2912        setInlineDelegator(!updating);
2913        setRemoveDelegator(!updating);
2914    }
2915
2916    /**
2917     * {@inheritDoc}
2918     */

2919    public final void setDeprecateDelegates(final boolean deprecate) {
2920        fDelegateDeprecation= deprecate;
2921    }
2922
2923    /**
2924     * Determines whether the delegator has to be inlined.
2925     *
2926     * @param inline
2927     * <code>true</code> to inline the delegator,
2928     * <code>false</code> otherwise
2929     */

2930    public final void setInlineDelegator(final boolean inline) {
2931        fInline= inline;
2932    }
2933
2934    /**
2935     * Sets the new method name.
2936     *
2937     * @param name
2938     * the name to set
2939     * @return the status of the operation
2940     */

2941    public final RefactoringStatus setMethodName(final String JavaDoc name) {
2942        Assert.isNotNull(name);
2943        RefactoringStatus status= Checks.checkMethodName(name);
2944        if (status.hasFatalError())
2945            return status;
2946        fMethodName= name;
2947        return status;
2948    }
2949
2950    /**
2951     * Determines whether the delegator has to be removed after inlining. Note
2952     * that the option to inline the delegator has to be enabled if this method
2953     * is called with the argument <code>true</code>.
2954     *
2955     * @param remove
2956     * <code>true</code> if it should be removed,
2957     * <code>false</code> otherwise
2958     */

2959    public final void setRemoveDelegator(final boolean remove) {
2960        Assert.isTrue(!remove || fInline);
2961        fRemove= remove;
2962    }
2963
2964    /**
2965     * Sets the new target.
2966     *
2967     * @param target
2968     * the target to set
2969     */

2970    public final void setTarget(final IVariableBinding target) {
2971        Assert.isNotNull(target);
2972        fTarget= target;
2973        fTargetType= null;
2974        try {
2975            final MethodDeclaration declaration= ASTNodeSearchUtil.getMethodDeclarationNode(fMethod, fSourceRewrite.getRoot());
2976            if (declaration != null) {
2977                final AstNodeFinder finder= new ThisReferenceFinder();
2978                declaration.accept(finder);
2979                fTargetNode= !finder.getResult().isEmpty();
2980                return;
2981            }
2982        } catch (JavaModelException exception) {
2983            JavaPlugin.log(exception);
2984        }
2985        fTargetNode= true;
2986    }
2987
2988    /**
2989     * Sets the new target name.
2990     *
2991     * @param name
2992     * the name to set
2993     * @return the status of the operation
2994     */

2995    public final RefactoringStatus setTargetName(final String JavaDoc name) {
2996        Assert.isNotNull(name);
2997        final RefactoringStatus status= Checks.checkTempName(name);
2998        if (status.hasFatalError())
2999            return status;
3000        fTargetName= name;
3001        return status;
3002    }
3003
3004    /**
3005     * Determines whether getter methods should be used to resolve visibility
3006     * issues.
3007     *
3008     * @param use
3009     * <code>true</code> if getter methods should be used,
3010     * <code>false</code> otherwise
3011     */

3012    public final void setUseGetters(final boolean use) {
3013        fUseGetters= use;
3014    }
3015
3016    /**
3017     * Determines whether setter methods should be used to resolve visibility
3018     * issues.
3019     *
3020     * @param use
3021     * <code>true</code> if setter methods should be used,
3022     * <code>false</code> otherwise
3023     */

3024    public final void setUseSetters(final boolean use) {
3025        fUseSetters= use;
3026    }
3027
3028    /**
3029     * Should getter methods be used to resolve visibility issues?
3030     *
3031     * @return <code>true</code> if getter methods should be used,
3032     * <code>false</code> otherwise
3033     */

3034    public final boolean shouldUseGetters() {
3035        return fUseGetters;
3036    }
3037
3038    /**
3039     * Should setter methods be used to resolve visibility issues?
3040     *
3041     * @return <code>true</code> if setter methods should be used,
3042     * <code>false</code> otherwise
3043     */

3044    public final boolean shouldUseSetters() {
3045        return fUseSetters;
3046    }
3047
3048    /**
3049     * Returns a best guess for the name of the new target.
3050     *
3051     * @return a best guess for the name
3052     */

3053    protected String JavaDoc suggestTargetName() {
3054        try {
3055            final String JavaDoc[] candidates= StubUtility.getArgumentNameSuggestions(fMethod.getDeclaringType(), computeReservedIdentifiers());
3056            if (candidates.length > 0) {
3057                if (candidates[0].indexOf('$') < 0)
3058                    return candidates[0];
3059            }
3060        } catch (JavaModelException exception) {
3061            JavaPlugin.log(exception);
3062        }
3063        return "arg"; //$NON-NLS-1$
3064
}
3065}
3066
Popular Tags