0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.structure;
0011:
0012: import java.util.ArrayList;
0013: import java.util.Arrays;
0014: import java.util.HashMap;
0015: import java.util.HashSet;
0016: import java.util.Iterator;
0017: import java.util.LinkedList;
0018: import java.util.List;
0019: import java.util.Map;
0020: import java.util.Set;
0021:
0022: import org.eclipse.text.edits.MultiTextEdit;
0023: import org.eclipse.text.edits.RangeMarker;
0024: import org.eclipse.text.edits.TextEdit;
0025: import org.eclipse.text.edits.TextEditGroup;
0026: import org.eclipse.text.edits.TextEditProcessor;
0027:
0028: import org.eclipse.core.runtime.Assert;
0029: import org.eclipse.core.runtime.CoreException;
0030: import org.eclipse.core.runtime.IProgressMonitor;
0031: import org.eclipse.core.runtime.IStatus;
0032: import org.eclipse.core.runtime.OperationCanceledException;
0033: import org.eclipse.core.runtime.Status;
0034: import org.eclipse.core.runtime.SubProgressMonitor;
0035:
0036: import org.eclipse.core.resources.IFile;
0037:
0038: import org.eclipse.jface.text.BadLocationException;
0039: import org.eclipse.jface.text.Document;
0040: import org.eclipse.jface.text.IDocument;
0041: import org.eclipse.jface.text.IRegion;
0042: import org.eclipse.jface.text.Region;
0043: import org.eclipse.jface.text.TextUtilities;
0044:
0045: import org.eclipse.ltk.core.refactoring.Change;
0046: import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0047: import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0048: import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
0049: import org.eclipse.ltk.core.refactoring.TextChange;
0050: import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
0051: import org.eclipse.ltk.core.refactoring.participants.MoveProcessor;
0052: import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0053: import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
0054: import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
0055:
0056: import org.eclipse.jdt.core.Flags;
0057: import org.eclipse.jdt.core.ICompilationUnit;
0058: import org.eclipse.jdt.core.IField;
0059: import org.eclipse.jdt.core.IJavaElement;
0060: import org.eclipse.jdt.core.IJavaProject;
0061: import org.eclipse.jdt.core.IMethod;
0062: import org.eclipse.jdt.core.IType;
0063: import org.eclipse.jdt.core.ITypeHierarchy;
0064: import org.eclipse.jdt.core.JavaCore;
0065: import org.eclipse.jdt.core.JavaModelException;
0066: import org.eclipse.jdt.core.dom.AST;
0067: import org.eclipse.jdt.core.dom.ASTNode;
0068: import org.eclipse.jdt.core.dom.ASTVisitor;
0069: import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
0070: import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
0071: import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
0072: import org.eclipse.jdt.core.dom.Assignment;
0073: import org.eclipse.jdt.core.dom.Block;
0074: import org.eclipse.jdt.core.dom.BodyDeclaration;
0075: import org.eclipse.jdt.core.dom.ClassInstanceCreation;
0076: import org.eclipse.jdt.core.dom.EnumDeclaration;
0077: import org.eclipse.jdt.core.dom.Expression;
0078: import org.eclipse.jdt.core.dom.FieldAccess;
0079: import org.eclipse.jdt.core.dom.IBinding;
0080: import org.eclipse.jdt.core.dom.IMethodBinding;
0081: import org.eclipse.jdt.core.dom.ITypeBinding;
0082: import org.eclipse.jdt.core.dom.IVariableBinding;
0083: import org.eclipse.jdt.core.dom.Javadoc;
0084: import org.eclipse.jdt.core.dom.MethodDeclaration;
0085: import org.eclipse.jdt.core.dom.MethodInvocation;
0086: import org.eclipse.jdt.core.dom.MethodRef;
0087: import org.eclipse.jdt.core.dom.MethodRefParameter;
0088: import org.eclipse.jdt.core.dom.Modifier;
0089: import org.eclipse.jdt.core.dom.Name;
0090: import org.eclipse.jdt.core.dom.NullLiteral;
0091: import org.eclipse.jdt.core.dom.PostfixExpression;
0092: import org.eclipse.jdt.core.dom.PrefixExpression;
0093: import org.eclipse.jdt.core.dom.PrimitiveType;
0094: import org.eclipse.jdt.core.dom.QualifiedName;
0095: import org.eclipse.jdt.core.dom.SimpleName;
0096: import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
0097: import org.eclipse.jdt.core.dom.SuperFieldAccess;
0098: import org.eclipse.jdt.core.dom.SuperMethodInvocation;
0099: import org.eclipse.jdt.core.dom.TagElement;
0100: import org.eclipse.jdt.core.dom.ThisExpression;
0101: import org.eclipse.jdt.core.dom.TypeDeclaration;
0102: import org.eclipse.jdt.core.dom.TypeParameter;
0103: import org.eclipse.jdt.core.dom.VariableDeclaration;
0104: import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
0105: import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
0106: import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0107: import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0108: import org.eclipse.jdt.core.refactoring.descriptors.MoveMethodDescriptor;
0109: import org.eclipse.jdt.core.search.IJavaSearchConstants;
0110: import org.eclipse.jdt.core.search.SearchMatch;
0111: import org.eclipse.jdt.core.search.SearchPattern;
0112:
0113: import org.eclipse.jdt.internal.corext.SourceRange;
0114: import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
0115: import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil;
0116: import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0117: import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0118: import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0119: import org.eclipse.jdt.internal.corext.dom.Bindings;
0120: import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
0121: import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
0122: import org.eclipse.jdt.internal.corext.refactoring.Checks;
0123: import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0124: import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0125: import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0126: import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0127: import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
0128: import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0129: import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
0130: import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0131: import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
0132: import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
0133: import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IVisibilityAdjustment;
0134: import org.eclipse.jdt.internal.corext.refactoring.tagging.ICommentProvider;
0135: import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
0136: import org.eclipse.jdt.internal.corext.refactoring.tagging.IScriptableRefactoring;
0137: import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
0138: import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0139: import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
0140: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0141: import org.eclipse.jdt.internal.corext.util.JdtFlags;
0142: import org.eclipse.jdt.internal.corext.util.Messages;
0143: import org.eclipse.jdt.internal.corext.util.SearchUtils;
0144: import org.eclipse.jdt.internal.corext.util.Strings;
0145:
0146: import org.eclipse.jdt.ui.JavaElementLabels;
0147:
0148: import org.eclipse.jdt.internal.ui.JavaPlugin;
0149: import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
0150: import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
0151:
0152: /**
0153: * Refactoring processor to move instance methods.
0154: */
0155: public final class MoveInstanceMethodProcessor extends MoveProcessor
0156: implements IScriptableRefactoring, IDelegateUpdating,
0157: ICommentProvider {
0158:
0159: /**
0160: * AST visitor to find references to parameters occurring in anonymous
0161: * classes of a method body.
0162: */
0163: public final class AnonymousClassReferenceFinder extends
0164: AstNodeFinder {
0165:
0166: /** The anonymous class nesting counter */
0167: protected int fAnonymousClass = 0;
0168:
0169: /** The declaring type of the method declaration */
0170: protected final ITypeBinding fDeclaringType;
0171:
0172: /**
0173: * Creates a new anonymous class reference finder.
0174: *
0175: * @param declaration
0176: * the method declaration to search for references
0177: */
0178: public AnonymousClassReferenceFinder(
0179: final MethodDeclaration declaration) {
0180: fDeclaringType = declaration.resolveBinding()
0181: .getDeclaringClass();
0182: }
0183:
0184: public final void endVisit(final AnonymousClassDeclaration node) {
0185: Assert.isNotNull(node);
0186: if (fAnonymousClass > 0)
0187: fAnonymousClass--;
0188: super .endVisit(node);
0189: }
0190:
0191: public final boolean visit(final AnonymousClassDeclaration node) {
0192: Assert.isNotNull(node);
0193: fAnonymousClass++;
0194: return super .visit(node);
0195: }
0196:
0197: public final boolean visit(final MethodInvocation node) {
0198: Assert.isNotNull(node);
0199: if (fAnonymousClass > 0) {
0200: final IMethodBinding binding = node
0201: .resolveMethodBinding();
0202: if (binding != null) {
0203: if (node.getExpression() == null
0204: && !Modifier.isStatic(binding
0205: .getModifiers()))
0206: fResult.add(node.getName());
0207: }
0208: }
0209: return true;
0210: }
0211:
0212: public boolean visit(final SimpleName node) {
0213: Assert.isNotNull(node);
0214: if (fAnonymousClass > 0) {
0215: if (!(node.getParent() instanceof FieldAccess)) {
0216: final IBinding binding = node.resolveBinding();
0217: if (binding instanceof IVariableBinding) {
0218: final IVariableBinding variable = (IVariableBinding) binding;
0219: final ITypeBinding declaring = variable
0220: .getDeclaringClass();
0221: if (declaring != null
0222: && Bindings.equals(declaring,
0223: fDeclaringType))
0224: fResult.add(node);
0225: }
0226: }
0227: }
0228: return false;
0229: }
0230: }
0231:
0232: /**
0233: * Partial implementation of an ast node finder.
0234: */
0235: protected static class AstNodeFinder extends ASTVisitor {
0236:
0237: /** The found ast nodes */
0238: protected final Set fResult = new HashSet();
0239:
0240: /** The status of the find operation */
0241: protected final RefactoringStatus fStatus = new RefactoringStatus();
0242:
0243: /**
0244: * Returns the result set.
0245: *
0246: * @return the result set
0247: */
0248: public final Set getResult() {
0249: return fResult;
0250: }
0251:
0252: /**
0253: * Returns the status of the find operation.
0254: *
0255: * @return the status of the operation
0256: */
0257: public final RefactoringStatus getStatus() {
0258: return fStatus;
0259: }
0260: }
0261:
0262: class DelegateInstanceMethodCreator extends DelegateMethodCreator {
0263:
0264: private Map fAdjustments;
0265:
0266: private boolean fNeededInsertion;
0267:
0268: private Map fRewrites;
0269:
0270: public DelegateInstanceMethodCreator(Map adjustments,
0271: Map rewrites) {
0272: super ();
0273: fAdjustments = adjustments;
0274: fRewrites = rewrites;
0275: }
0276:
0277: protected ASTNode createBody(BodyDeclaration bd)
0278: throws JavaModelException {
0279: MethodDeclaration methodDeclaration = (MethodDeclaration) bd;
0280: final MethodInvocation invocation = getAst()
0281: .newMethodInvocation();
0282: invocation.setName(getAst().newSimpleName(
0283: getNewElementName()));
0284: invocation
0285: .setExpression(createSimpleTargetAccessExpression(methodDeclaration));
0286: fNeededInsertion = createArgumentList(methodDeclaration,
0287: invocation.arguments(),
0288: new VisibilityAdjustingArgumentFactory(getAst(),
0289: fRewrites, fAdjustments));
0290: final Block block = getAst().newBlock();
0291: block.statements().add(
0292: createMethodInvocation(methodDeclaration,
0293: invocation));
0294: if (!fSourceRewrite.getCu().equals(
0295: fTargetType.getCompilationUnit()))
0296: fSourceRewrite.getImportRemover().registerRemovedNode(
0297: methodDeclaration.getBody());
0298: return block;
0299: }
0300:
0301: protected ASTNode createDocReference(
0302: final BodyDeclaration declaration)
0303: throws JavaModelException {
0304: return MoveInstanceMethodProcessor.this
0305: .createMethodReference(
0306: (MethodDeclaration) declaration, getAst());
0307: }
0308:
0309: protected boolean getNeededInsertion() {
0310: return fNeededInsertion;
0311: }
0312: }
0313:
0314: /**
0315: * AST visitor to find 'this' references to enclosing instances.
0316: */
0317: public final class EnclosingInstanceReferenceFinder extends
0318: AstNodeFinder {
0319:
0320: /** The list of enclosing types */
0321: private final List fEnclosingTypes = new ArrayList(3);
0322:
0323: /**
0324: * Creates a new enclosing instance reference finder.
0325: *
0326: * @param binding
0327: * the declaring type
0328: */
0329: public EnclosingInstanceReferenceFinder(
0330: final ITypeBinding binding) {
0331: Assert.isNotNull(binding);
0332: ITypeBinding declaring = binding.getDeclaringClass();
0333: while (declaring != null) {
0334: fEnclosingTypes.add(declaring);
0335: declaring = declaring.getDeclaringClass();
0336: }
0337: }
0338:
0339: public final boolean visit(final SimpleName node) {
0340: Assert.isNotNull(node);
0341: final IBinding binding = node.resolveBinding();
0342: ITypeBinding declaring = null;
0343: if (binding instanceof IVariableBinding) {
0344: final IVariableBinding variable = (IVariableBinding) binding;
0345: if (Flags.isStatic(variable.getModifiers()))
0346: return false;
0347: declaring = variable.getDeclaringClass();
0348: } else if (binding instanceof IMethodBinding) {
0349: final IMethodBinding method = (IMethodBinding) binding;
0350: if (Flags.isStatic(method.getModifiers()))
0351: return false;
0352: declaring = method.getDeclaringClass();
0353: }
0354: if (declaring != null) {
0355: ITypeBinding enclosing = null;
0356: for (final Iterator iterator = fEnclosingTypes
0357: .iterator(); iterator.hasNext();) {
0358: enclosing = (ITypeBinding) iterator.next();
0359: if (Bindings.equals(enclosing, declaring)) {
0360: fStatus
0361: .merge(RefactoringStatus
0362: .createFatalErrorStatus(
0363: RefactoringCoreMessages.MoveInstanceMethodProcessor_refers_enclosing_instances,
0364: JavaStatusContext
0365: .create(
0366: fMethod
0367: .getCompilationUnit(),
0368: node)));
0369: fResult.add(node);
0370: break;
0371: }
0372: }
0373: }
0374: return false;
0375: }
0376:
0377: public final boolean visit(final ThisExpression node) {
0378: Assert.isNotNull(node);
0379: if (node.getQualifier() != null) {
0380: fStatus
0381: .merge(RefactoringStatus
0382: .createFatalErrorStatus(
0383: RefactoringCoreMessages.MoveInstanceMethodProcessor_refers_enclosing_instances,
0384: JavaStatusContext
0385: .create(
0386: fMethod
0387: .getCompilationUnit(),
0388: node)));
0389: fResult.add(node);
0390: }
0391: return false;
0392: }
0393: }
0394:
0395: /**
0396: * AST visitor to find references to type variables or generic types.
0397: */
0398: public final class GenericReferenceFinder extends AstNodeFinder {
0399:
0400: /** The type parameter binding keys */
0401: protected final Set fBindings = new HashSet();
0402:
0403: /**
0404: * Creates a new generic reference finder.
0405: *
0406: * @param declaration
0407: * the method declaration
0408: */
0409: public GenericReferenceFinder(
0410: final MethodDeclaration declaration) {
0411: Assert.isNotNull(declaration);
0412: ITypeBinding binding = null;
0413: TypeParameter parameter = null;
0414: for (final Iterator iterator = declaration.typeParameters()
0415: .iterator(); iterator.hasNext();) {
0416: parameter = (TypeParameter) iterator.next();
0417: binding = parameter.resolveBinding();
0418: if (binding != null)
0419: fBindings.add(binding.getKey());
0420: }
0421: }
0422:
0423: /*
0424: * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleName)
0425: */
0426: public final boolean visit(final SimpleName node) {
0427: Assert.isNotNull(node);
0428: final IBinding binding = node.resolveBinding();
0429: if (binding instanceof ITypeBinding) {
0430: final ITypeBinding type = (ITypeBinding) binding;
0431: if (!fBindings.contains(type.getKey())
0432: && type.isTypeVariable()) {
0433: fResult.add(node);
0434: fStatus
0435: .merge(RefactoringStatus
0436: .createFatalErrorStatus(
0437: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_type_variables,
0438: JavaStatusContext
0439: .create(
0440: fMethod
0441: .getCompilationUnit(),
0442: node)));
0443: return false;
0444: }
0445: }
0446: return true;
0447: }
0448: }
0449:
0450: /**
0451: * Factory for method argument declaration or expression nodes.
0452: */
0453: protected static interface IArgumentFactory {
0454:
0455: /**
0456: * Returns a argument node for the specified variable binding.
0457: *
0458: * @param binding
0459: * the binding to create a argument node for
0460: * @param last
0461: * <code>true</code> if the argument represented by this
0462: * node is the last one in its declaring method
0463: * @return the corresponding node
0464: * @throws JavaModelException
0465: * if an error occurs
0466: */
0467: public ASTNode getArgumentNode(IVariableBinding binding,
0468: boolean last) throws JavaModelException;
0469:
0470: /**
0471: * Returns a target node for the current target.
0472: *
0473: * @return the corresponding node
0474: * @throws JavaModelException
0475: * if an error occurs
0476: */
0477: public ASTNode getTargetNode() throws JavaModelException;
0478: }
0479:
0480: /**
0481: * AST visitor to rewrite the body of the moved method.
0482: */
0483: public final class MethodBodyRewriter extends ASTVisitor {
0484:
0485: /** The anonymous class nesting counter */
0486: protected int fAnonymousClass = 0;
0487:
0488: /** The method declaration to rewrite */
0489: protected final MethodDeclaration fDeclaration;
0490:
0491: /** The set of handled method invocations */
0492: protected final Set fMethodDeclarations = new HashSet();
0493:
0494: /** The source ast rewrite to use */
0495: protected final ASTRewrite fRewrite;
0496:
0497: /** The existing static imports */
0498: protected final Set fStaticImports = new HashSet();
0499:
0500: /** The refactoring status */
0501: protected final RefactoringStatus fStatus = new RefactoringStatus();
0502:
0503: /** The target compilation unit rewrite to use */
0504: protected final CompilationUnitRewrite fTargetRewrite;
0505:
0506: /**
0507: * Creates a new method body rewriter.
0508: *
0509: * @param targetRewrite
0510: * the target compilation unit rewrite to use
0511: * @param rewrite
0512: * the source ast rewrite to use
0513: * @param sourceDeclaration
0514: * the source method declaration
0515: */
0516: public MethodBodyRewriter(
0517: final CompilationUnitRewrite targetRewrite,
0518: final ASTRewrite rewrite,
0519: final MethodDeclaration sourceDeclaration) {
0520: Assert.isNotNull(targetRewrite);
0521: Assert.isNotNull(rewrite);
0522: Assert.isNotNull(sourceDeclaration);
0523: fTargetRewrite = targetRewrite;
0524: fRewrite = rewrite;
0525: fDeclaration = sourceDeclaration;
0526: fStaticImports.clear();
0527: ImportRewriteUtil.collectImports(fMethod.getJavaProject(),
0528: sourceDeclaration, new HashSet(), fStaticImports,
0529: false);
0530: }
0531:
0532: public final void endVisit(final AnonymousClassDeclaration node) {
0533: Assert.isNotNull(node);
0534: if (fAnonymousClass > 0)
0535: fAnonymousClass--;
0536: super .endVisit(node);
0537: }
0538:
0539: public final boolean visit(final AnonymousClassDeclaration node) {
0540: Assert.isNotNull(node);
0541: fAnonymousClass++;
0542: return super .visit(node);
0543: }
0544:
0545: public final boolean visit(final ClassInstanceCreation node) {
0546: Assert.isNotNull(node);
0547: if (node.getParent() instanceof ClassInstanceCreation) {
0548: final AnonymousClassDeclaration declaration = node
0549: .getAnonymousClassDeclaration();
0550: if (declaration != null)
0551: visit(declaration);
0552: return false;
0553: }
0554: return super .visit(node);
0555: }
0556:
0557: public final boolean visit(final FieldAccess node) {
0558: Assert.isNotNull(node);
0559: final Expression expression = node.getExpression();
0560: final IVariableBinding variable = node
0561: .resolveFieldBinding();
0562: final AST ast = fRewrite.getAST();
0563: if (expression instanceof ThisExpression) {
0564: if (Bindings.equals(fTarget, variable)) {
0565: if (fAnonymousClass > 0) {
0566: final ThisExpression target = ast
0567: .newThisExpression();
0568: target.setQualifier(ast
0569: .newSimpleName(fTargetType
0570: .getElementName()));
0571: fRewrite.replace(node, target, null);
0572: } else
0573: fRewrite.replace(node, ast.newThisExpression(),
0574: null);
0575: return false;
0576: }
0577: }
0578: if (expression instanceof FieldAccess) {
0579: final FieldAccess access = (FieldAccess) expression;
0580: final IBinding binding = access.getName()
0581: .resolveBinding();
0582: if ((access.getExpression() instanceof ThisExpression)
0583: && Bindings.equals(fTarget, binding)) {
0584: fRewrite.replace(node, ast.newSimpleName(node
0585: .getName().getIdentifier()), null);
0586: return false;
0587: }
0588: } else if (expression != null) {
0589: final IMethodBinding method = fDeclaration
0590: .resolveBinding();
0591: if (variable != null
0592: && method != null
0593: && !JdtFlags.isStatic(variable)
0594: && Bindings.equals(method.getDeclaringClass(),
0595: variable.getDeclaringClass())) {
0596: fRewrite.replace(expression, ast
0597: .newSimpleName(fTargetName), null);
0598: return false;
0599: }
0600: }
0601: return true;
0602: }
0603:
0604: public final void visit(final List nodes) {
0605: Assert.isNotNull(nodes);
0606: ASTNode node = null;
0607: for (final Iterator iterator = nodes.iterator(); iterator
0608: .hasNext();) {
0609: node = (ASTNode) iterator.next();
0610: node.accept(this );
0611: }
0612: }
0613:
0614: public final boolean visit(final MethodInvocation node) {
0615: Assert.isNotNull(node);
0616: final Expression expression = node.getExpression();
0617: final IMethodBinding method = node.resolveMethodBinding();
0618: if (method != null) {
0619: final ASTRewrite rewrite = fRewrite;
0620: if (expression == null) {
0621: final AST ast = node.getAST();
0622: if (!JdtFlags.isStatic(method))
0623: rewrite.set(node,
0624: MethodInvocation.EXPRESSION_PROPERTY,
0625: ast.newSimpleName(fTargetName), null);
0626: else
0627: rewrite.set(node,
0628: MethodInvocation.EXPRESSION_PROPERTY,
0629: ast.newSimpleType(ast
0630: .newSimpleName(fMethod
0631: .getDeclaringType()
0632: .getElementName())),
0633: null);
0634: return true;
0635: } else {
0636: if (expression instanceof FieldAccess) {
0637: final FieldAccess access = (FieldAccess) expression;
0638: if (Bindings.equals(access
0639: .resolveFieldBinding(), fTarget)) {
0640: rewrite.remove(expression, null);
0641: visit(node.arguments());
0642: return false;
0643: }
0644: } else if (expression instanceof Name) {
0645: final Name name = (Name) expression;
0646: if (Bindings.equals(name.resolveBinding(),
0647: fTarget)) {
0648: rewrite.remove(expression, null);
0649: visit(node.arguments());
0650: return false;
0651: }
0652: }
0653: }
0654: }
0655: return true;
0656: }
0657:
0658: public final boolean visit(final QualifiedName node) {
0659: Assert.isNotNull(node);
0660: IBinding binding = node.resolveBinding();
0661: if (binding instanceof ITypeBinding) {
0662: final ITypeBinding type = (ITypeBinding) binding;
0663: if (type.isClass() && type.getDeclaringClass() != null) {
0664: final String name = fTargetRewrite
0665: .getImportRewrite().addImport(type);
0666: if (name != null && name.length() > 0) {
0667: fRewrite.replace(node, ASTNodeFactory.newName(
0668: node.getAST(), name), null);
0669: return false;
0670: }
0671: }
0672: }
0673: binding = node.getQualifier().resolveBinding();
0674: if (Bindings.equals(binding, fTarget)) {
0675: fRewrite.replace(node, fRewrite.createCopyTarget(node
0676: .getName()), null);
0677: return false;
0678: }
0679: return true;
0680: }
0681:
0682: public final boolean visit(final SimpleName node) {
0683: Assert.isNotNull(node);
0684: final AST ast = node.getAST();
0685: final ASTRewrite rewrite = fRewrite;
0686: final IBinding binding = node.resolveBinding();
0687: if (binding instanceof ITypeBinding) {
0688: final ITypeBinding type = (ITypeBinding) binding;
0689: if (type.isClass() && type.getDeclaringClass() != null) {
0690: final String name = fTargetRewrite
0691: .getImportRewrite().addImport(type);
0692: if (name != null && name.length() > 0) {
0693: fRewrite.replace(node, ASTNodeFactory.newName(
0694: ast, name), null);
0695: return false;
0696: }
0697: }
0698: }
0699: if (Bindings.equals(binding, fTarget))
0700: if (fAnonymousClass > 0) {
0701: final ThisExpression target = ast
0702: .newThisExpression();
0703: target.setQualifier(ast.newSimpleName(fTargetType
0704: .getElementName()));
0705: fRewrite.replace(node, target, null);
0706: } else
0707: rewrite
0708: .replace(node, ast.newThisExpression(),
0709: null);
0710: else if (binding instanceof IVariableBinding) {
0711: final IVariableBinding variable = (IVariableBinding) binding;
0712: final IMethodBinding method = fDeclaration
0713: .resolveBinding();
0714: final ITypeBinding declaring = variable
0715: .getDeclaringClass();
0716: if (method != null) {
0717: if (Bindings.equals(method.getDeclaringClass(),
0718: declaring)) {
0719: if (JdtFlags.isStatic(variable))
0720: rewrite
0721: .replace(
0722: node,
0723: ast
0724: .newQualifiedName(
0725: ASTNodeFactory
0726: .newName(
0727: ast,
0728: fTargetRewrite
0729: .getImportRewrite()
0730: .addImport(
0731: declaring)),
0732: ast
0733: .newSimpleName(node
0734: .getFullyQualifiedName())),
0735: null);
0736: else {
0737: final FieldAccess access = ast
0738: .newFieldAccess();
0739: access.setExpression(ast
0740: .newSimpleName(fTargetName));
0741: access.setName(ast.newSimpleName(node
0742: .getFullyQualifiedName()));
0743: rewrite.replace(node, access, null);
0744: }
0745: } else if (!(node.getParent() instanceof QualifiedName)
0746: && JdtFlags.isStatic(variable)
0747: && !fStaticImports.contains(variable)) {
0748: rewrite.replace(node, ast.newQualifiedName(
0749: ASTNodeFactory.newName(ast,
0750: fTargetRewrite
0751: .getImportRewrite()
0752: .addImport(declaring)),
0753: ast.newSimpleName(node
0754: .getFullyQualifiedName())),
0755: null);
0756: }
0757: }
0758: }
0759: return false;
0760: }
0761:
0762: public final boolean visit(final ThisExpression node) {
0763: Assert.isNotNull(node);
0764: fRewrite.replace(node, node.getAST().newSimpleName(
0765: fTargetName), null);
0766: return false;
0767: }
0768: }
0769:
0770: /**
0771: * AST visitor to find read-only fields of the declaring class of 'this'.
0772: */
0773: public static class ReadyOnlyFieldFinder extends ASTVisitor {
0774:
0775: /**
0776: * Returns the field binding associated with this expression.
0777: *
0778: * @param expression
0779: * the expression to get the field binding for
0780: * @return the field binding, if the expression denotes a field access
0781: * or a field name, <code>null</code> otherwise
0782: */
0783: protected static IVariableBinding getFieldBinding(
0784: final Expression expression) {
0785: Assert.isNotNull(expression);
0786: if (expression instanceof FieldAccess)
0787: return (IVariableBinding) ((FieldAccess) expression)
0788: .getName().resolveBinding();
0789: if (expression instanceof Name) {
0790: final IBinding binding = ((Name) expression)
0791: .resolveBinding();
0792: if (binding instanceof IVariableBinding) {
0793: final IVariableBinding variable = (IVariableBinding) binding;
0794: if (variable.isField())
0795: return variable;
0796: }
0797: }
0798: return null;
0799: }
0800:
0801: /**
0802: * Is the specified name a qualified entity, e.g. preceded by 'this',
0803: * 'super' or part of a method invocation?
0804: *
0805: * @param name
0806: * the name to check
0807: * @return <code>true</code> if this entity is qualified,
0808: * <code>false</code> otherwise
0809: */
0810: protected static boolean isQualifiedEntity(final Name name) {
0811: Assert.isNotNull(name);
0812: final ASTNode parent = name.getParent();
0813: if ((parent instanceof QualifiedName && ((QualifiedName) parent)
0814: .getName().equals(name))
0815: || (parent instanceof FieldAccess && ((FieldAccess) parent)
0816: .getName().equals(name))
0817: || (parent instanceof SuperFieldAccess))
0818: return true;
0819: else if (parent instanceof MethodInvocation) {
0820: final MethodInvocation invocation = (MethodInvocation) parent;
0821: return invocation.getExpression() != null
0822: && invocation.getName().equals(name);
0823: }
0824: return false;
0825: }
0826:
0827: /** The list of found bindings */
0828: protected final List fBindings = new LinkedList();
0829:
0830: /** The keys of the found bindings */
0831: protected final Set fFound = new HashSet();
0832:
0833: /** The keys of the written bindings */
0834: protected final Set fWritten = new HashSet();
0835:
0836: /**
0837: * Creates a new read only field finder.
0838: *
0839: * @param binding
0840: * The declaring class of the method declaring to find fields
0841: * for
0842: */
0843: public ReadyOnlyFieldFinder(final ITypeBinding binding) {
0844: Assert.isNotNull(binding);
0845: final IVariableBinding[] bindings = binding
0846: .getDeclaredFields();
0847: IVariableBinding variable = null;
0848: for (int index = 0; index < bindings.length; index++) {
0849: variable = bindings[index];
0850: if (!variable.isSynthetic()
0851: && !fFound.contains(variable.getKey())) {
0852: fFound.add(variable.getKey());
0853: fBindings.add(variable);
0854: }
0855: }
0856: }
0857:
0858: /**
0859: * Returns all fields of the declaring class plus the ones references in
0860: * the visited method declaration.
0861: *
0862: * @return all fields of the declaring class plus the references ones
0863: */
0864: public final IVariableBinding[] getDeclaredFields() {
0865: final IVariableBinding[] result = new IVariableBinding[fBindings
0866: .size()];
0867: fBindings.toArray(result);
0868: return result;
0869: }
0870:
0871: /**
0872: * Returns all fields of the declaring class which are not written by
0873: * the visited method declaration.
0874: *
0875: * @return all fields which are not written
0876: */
0877: public final IVariableBinding[] getReadOnlyFields() {
0878: IVariableBinding binding = null;
0879: final List list = new LinkedList(fBindings);
0880: for (final Iterator iterator = list.iterator(); iterator
0881: .hasNext();) {
0882: binding = (IVariableBinding) iterator.next();
0883: if (fWritten.contains(binding.getKey()))
0884: iterator.remove();
0885: }
0886: final IVariableBinding[] result = new IVariableBinding[list
0887: .size()];
0888: list.toArray(result);
0889: return result;
0890: }
0891:
0892: public final boolean visit(final Assignment node) {
0893: Assert.isNotNull(node);
0894: final IVariableBinding binding = getFieldBinding(node
0895: .getLeftHandSide());
0896: if (binding != null)
0897: fWritten.add(binding.getKey());
0898: return true;
0899: }
0900:
0901: public final boolean visit(final FieldAccess node) {
0902: Assert.isNotNull(node);
0903: if (node.getExpression() instanceof ThisExpression) {
0904: final IVariableBinding binding = (IVariableBinding) node
0905: .getName().resolveBinding();
0906: if (binding != null) {
0907: final String key = binding.getKey();
0908: if (!fFound.contains(key)) {
0909: fFound.add(key);
0910: fBindings.add(binding);
0911: }
0912: }
0913: }
0914: return true;
0915: }
0916:
0917: public final boolean visit(final PostfixExpression node) {
0918: final IVariableBinding binding = getFieldBinding(node
0919: .getOperand());
0920: if (binding != null)
0921: fWritten.add(binding.getKey());
0922: return true;
0923: }
0924:
0925: public final boolean visit(final PrefixExpression node) {
0926: final IVariableBinding binding = getFieldBinding(node
0927: .getOperand());
0928: if (binding != null)
0929: fWritten.add(binding.getKey());
0930: return false;
0931: }
0932:
0933: public final boolean visit(final SimpleName node) {
0934: Assert.isNotNull(node);
0935: final IBinding binding = node.resolveBinding();
0936: if (binding != null)
0937: if (isFieldAccess(node) && !isQualifiedEntity(node)) {
0938: final IVariableBinding variable = (IVariableBinding) binding;
0939: final String key = variable.getKey();
0940: if (!fFound.contains(key)) {
0941: fFound.add(key);
0942: fBindings.add(variable);
0943: }
0944: }
0945: return false;
0946: }
0947: }
0948:
0949: /**
0950: * AST visitor to find recursive calls to the method.
0951: */
0952: public final class RecursiveCallFinder extends AstNodeFinder {
0953:
0954: /** The method binding */
0955: protected final IMethodBinding fBinding;
0956:
0957: /**
0958: * Creates a new recursive call finder.
0959: *
0960: * @param declaration
0961: * the method declaration
0962: */
0963: public RecursiveCallFinder(final MethodDeclaration declaration) {
0964: Assert.isNotNull(declaration);
0965: fBinding = declaration.resolveBinding();
0966: }
0967:
0968: public final boolean visit(final MethodInvocation node) {
0969: Assert.isNotNull(node);
0970: final Expression expression = node.getExpression();
0971: final IMethodBinding binding = node.resolveMethodBinding();
0972: if (binding == null
0973: || (!Modifier.isStatic(binding.getModifiers())
0974: && Bindings.equals(binding, fBinding) && (expression == null || expression instanceof ThisExpression))) {
0975: fStatus
0976: .merge(RefactoringStatus
0977: .createFatalErrorStatus(
0978: RefactoringCoreMessages.MoveInstanceMethodProcessor_potentially_recursive,
0979: JavaStatusContext
0980: .create(
0981: fMethod
0982: .getCompilationUnit(),
0983: node)));
0984: fResult.add(node);
0985: return false;
0986: }
0987: return true;
0988: }
0989: }
0990:
0991: /**
0992: * AST visitor to find 'super' references.
0993: */
0994: public final class SuperReferenceFinder extends AstNodeFinder {
0995:
0996: public final boolean visit(final AnnotationTypeDeclaration node) {
0997: return false;
0998: }
0999:
1000: public final boolean visit(final AnonymousClassDeclaration node) {
1001: return false;
1002: }
1003:
1004: public final boolean visit(final EnumDeclaration node) {
1005: return false;
1006: }
1007:
1008: public final boolean visit(final SuperFieldAccess node) {
1009: Assert.isNotNull(node);
1010: fStatus
1011: .merge(RefactoringStatus
1012: .createFatalErrorStatus(
1013: RefactoringCoreMessages.MoveInstanceMethodProcessor_uses_super ,
1014: JavaStatusContext
1015: .create(
1016: fMethod
1017: .getCompilationUnit(),
1018: node)));
1019: fResult.add(node);
1020: return false;
1021: }
1022:
1023: public final boolean visit(final SuperMethodInvocation node) {
1024: Assert.isNotNull(node);
1025: fStatus
1026: .merge(RefactoringStatus
1027: .createFatalErrorStatus(
1028: RefactoringCoreMessages.MoveInstanceMethodProcessor_uses_super ,
1029: JavaStatusContext
1030: .create(
1031: fMethod
1032: .getCompilationUnit(),
1033: node)));
1034: fResult.add(node);
1035: return false;
1036: }
1037:
1038: public final boolean visit(final TypeDeclaration node) {
1039: return false;
1040: }
1041: }
1042:
1043: /**
1044: * AST visitor to find references to 'this'.
1045: */
1046: public final class ThisReferenceFinder extends AstNodeFinder {
1047:
1048: public final boolean visit(final MethodInvocation node) {
1049: Assert.isNotNull(node);
1050: final IMethodBinding binding = node.resolveMethodBinding();
1051: if (binding != null && !JdtFlags.isStatic(binding)
1052: && node.getExpression() == null) {
1053: fResult.add(node);
1054: fStatus
1055: .merge(RefactoringStatus
1056: .createFatalErrorStatus(
1057: RefactoringCoreMessages.MoveInstanceMethodProcessor_this _reference,
1058: JavaStatusContext
1059: .create(
1060: fMethod
1061: .getCompilationUnit(),
1062: node)));
1063: }
1064: return true;
1065: }
1066:
1067: public final boolean visit(final SimpleName node) {
1068: Assert.isNotNull(node);
1069: if (isFieldAccess(node) && !isTargetAccess(node)) {
1070: fResult.add(node);
1071: fStatus
1072: .merge(RefactoringStatus
1073: .createFatalErrorStatus(
1074: RefactoringCoreMessages.MoveInstanceMethodProcessor_this _reference,
1075: JavaStatusContext
1076: .create(
1077: fMethod
1078: .getCompilationUnit(),
1079: node)));
1080: }
1081: return false;
1082: }
1083:
1084: public final boolean visit(final ThisExpression node) {
1085: Assert.isNotNull(node);
1086: fResult.add(node);
1087: fStatus
1088: .merge(RefactoringStatus
1089: .createFatalErrorStatus(
1090: RefactoringCoreMessages.MoveInstanceMethodProcessor_this _reference,
1091: JavaStatusContext
1092: .create(
1093: fMethod
1094: .getCompilationUnit(),
1095: node)));
1096: return false;
1097: }
1098: }
1099:
1100: /**
1101: * Argument factory which adjusts the visibilities of the argument types.
1102: */
1103: public class VisibilityAdjustingArgumentFactory implements
1104: IArgumentFactory {
1105:
1106: /** The visibility adjustments */
1107: private final Map fAdjustments;
1108:
1109: /** The ast to use for new nodes */
1110: private final AST fAst;
1111:
1112: /** The compilation unit rewrites */
1113: private final Map fRewrites;
1114:
1115: /**
1116: * Creates a new visibility adjusting argument factory.
1117: *
1118: * @param ast
1119: * the ast to use for new nodes
1120: * @param rewrites
1121: * the compilation unit rewrites
1122: * @param adjustments
1123: * the map of elements to visibility adjustments
1124: */
1125: public VisibilityAdjustingArgumentFactory(final AST ast,
1126: final Map rewrites, final Map adjustments) {
1127: Assert.isNotNull(ast);
1128: Assert.isNotNull(rewrites);
1129: Assert.isNotNull(adjustments);
1130: fAst = ast;
1131: fRewrites = rewrites;
1132: fAdjustments = adjustments;
1133: }
1134:
1135: protected final void adjustTypeVisibility(
1136: final ITypeBinding binding) throws JavaModelException {
1137: Assert.isNotNull(binding);
1138: final IJavaElement element = binding.getJavaElement();
1139: if (element instanceof IType) {
1140: final IType type = (IType) element;
1141: if (!type.isBinary() && !type.isReadOnly()
1142: && !Flags.isPublic(type.getFlags())) {
1143: boolean same = false;
1144: final CompilationUnitRewrite rewrite = getCompilationUnitRewrite(
1145: fRewrites, type.getCompilationUnit());
1146: final AbstractTypeDeclaration declaration = ASTNodeSearchUtil
1147: .getAbstractTypeDeclarationNode(type,
1148: rewrite.getRoot());
1149: if (declaration != null) {
1150: final ITypeBinding declaring = declaration
1151: .resolveBinding();
1152: if (declaring != null
1153: && Bindings
1154: .equals(binding.getPackage(),
1155: fTarget.getType()
1156: .getPackage()))
1157: same = true;
1158: final Modifier.ModifierKeyword keyword = same ? null
1159: : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
1160: final String modifier = same ? RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_default
1161: : RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_public;
1162: if (MemberVisibilityAdjustor
1163: .hasLowerVisibility(
1164: binding.getModifiers(),
1165: same ? Modifier.NONE
1166: : (keyword == null ? Modifier.NONE
1167: : keyword
1168: .toFlagValue()))
1169: && MemberVisibilityAdjustor
1170: .needsVisibilityAdjustments(
1171: type, keyword,
1172: fAdjustments))
1173: fAdjustments
1174: .put(
1175: type,
1176: new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(
1177: type,
1178: keyword,
1179: RefactoringStatus
1180: .createWarningStatus(
1181: Messages
1182: .format(
1183: RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_type_warning,
1184: new String[] {
1185: BindingLabelProvider
1186: .getBindingLabel(
1187: declaration
1188: .resolveBinding(),
1189: JavaElementLabels.ALL_FULLY_QUALIFIED),
1190: modifier }),
1191: JavaStatusContext
1192: .create(
1193: type
1194: .getCompilationUnit(),
1195: declaration))));
1196: }
1197: }
1198: }
1199: }
1200:
1201: public ASTNode getArgumentNode(final IVariableBinding binding,
1202: final boolean last) throws JavaModelException {
1203: Assert.isNotNull(binding);
1204: adjustTypeVisibility(binding.getType());
1205: return fAst.newSimpleName(binding.getName());
1206: }
1207:
1208: public ASTNode getTargetNode() throws JavaModelException {
1209: return fAst.newThisExpression();
1210: }
1211: }
1212:
1213: private static final String ATTRIBUTE_DEPRECATE = "deprecate"; //$NON-NLS-1$
1214:
1215: private static final String ATTRIBUTE_INLINE = "inline"; //$NON-NLS-1$
1216:
1217: private static final String ATTRIBUTE_REMOVE = "remove"; //$NON-NLS-1$
1218:
1219: private static final String ATTRIBUTE_TARGET_INDEX = "targetIndex"; //$NON-NLS-1$
1220:
1221: private static final String ATTRIBUTE_TARGET_NAME = "targetName"; //$NON-NLS-1$
1222:
1223: private static final String ATTRIBUTE_USE_GETTER = "getter"; //$NON-NLS-1$
1224:
1225: private static final String ATTRIBUTE_USE_SETTER = "setter"; //$NON-NLS-1$
1226:
1227: /** The identifier of this processor */
1228: public static final String IDENTIFIER = "org.eclipse.jdt.ui.moveInstanceMethodProcessor"; //$NON-NLS-1$
1229:
1230: /**
1231: * Returns the bindings of the method arguments of the specified
1232: * declaration.
1233: *
1234: * @param declaration
1235: * the method declaration
1236: * @return the array of method argument variable bindings
1237: */
1238: protected static IVariableBinding[] getArgumentBindings(
1239: final MethodDeclaration declaration) {
1240: Assert.isNotNull(declaration);
1241: final List parameters = new ArrayList(declaration.parameters()
1242: .size());
1243: VariableDeclaration variable = null;
1244: IVariableBinding binding = null;
1245: for (final Iterator iterator = declaration.parameters()
1246: .iterator(); iterator.hasNext();) {
1247: variable = (VariableDeclaration) iterator.next();
1248: binding = variable.resolveBinding();
1249: if (binding == null)
1250: return new IVariableBinding[0];
1251: parameters.add(binding);
1252: }
1253: final IVariableBinding[] result = new IVariableBinding[parameters
1254: .size()];
1255: parameters.toArray(result);
1256: return result;
1257: }
1258:
1259: /**
1260: * Returns the bindings of the method argument types of the specified
1261: * declaration.
1262: *
1263: * @param declaration
1264: * the method declaration
1265: * @return the array of method argument variable bindings
1266: */
1267: protected static ITypeBinding[] getArgumentTypes(
1268: final MethodDeclaration declaration) {
1269: Assert.isNotNull(declaration);
1270: final IVariableBinding[] parameters = getArgumentBindings(declaration);
1271: final List types = new ArrayList(parameters.length);
1272: IVariableBinding binding = null;
1273: ITypeBinding type = null;
1274: for (int index = 0; index < parameters.length; index++) {
1275: binding = parameters[index];
1276: type = binding.getType();
1277: if (type != null)
1278: types.add(type);
1279: }
1280: final ITypeBinding[] result = new ITypeBinding[types.size()];
1281: types.toArray(result);
1282: return result;
1283: }
1284:
1285: /**
1286: * Is the specified name a field access?
1287: *
1288: * @param name
1289: * the name to check
1290: * @return <code>true</code> if this name is a field access,
1291: * <code>false</code> otherwise
1292: */
1293: protected static boolean isFieldAccess(final SimpleName name) {
1294: Assert.isNotNull(name);
1295: final IBinding binding = name.resolveBinding();
1296: if (!(binding instanceof IVariableBinding))
1297: return false;
1298: final IVariableBinding variable = (IVariableBinding) binding;
1299: if (!variable.isField())
1300: return false;
1301: if ("length".equals(name.getIdentifier())) { //$NON-NLS-1$
1302: final ASTNode parent = name.getParent();
1303: if (parent instanceof QualifiedName) {
1304: final QualifiedName qualified = (QualifiedName) parent;
1305: final ITypeBinding type = qualified.getQualifier()
1306: .resolveTypeBinding();
1307: if (type != null && type.isArray())
1308: return false;
1309: }
1310: }
1311: return !Modifier.isStatic(variable.getModifiers());
1312: }
1313:
1314: /** The candidate targets */
1315: private IVariableBinding[] fCandidateTargets = new IVariableBinding[0];
1316:
1317: /** The text change manager */
1318: private TextChangeManager fChangeManager = null;
1319:
1320: /** The comment */
1321: private String fComment;
1322:
1323: /** Should the delegator be deprecated? */
1324: private boolean fDelegateDeprecation = true;
1325:
1326: private boolean fDelegatingUpdating;
1327:
1328: /** Should the delegator be inlined? */
1329: private boolean fInline = false;
1330:
1331: /** The method to move */
1332: private IMethod fMethod;
1333:
1334: /** The name of the new method to generate */
1335: private String fMethodName;
1336:
1337: /** The possible targets */
1338: private IVariableBinding[] fPossibleTargets = new IVariableBinding[0];
1339:
1340: /** Should the delegator be removed after inlining? */
1341: private boolean fRemove = false;
1342:
1343: /** The code generation settings to apply */
1344: private CodeGenerationSettings fSettings;
1345:
1346: /** The source compilation unit rewrite */
1347: private CompilationUnitRewrite fSourceRewrite;
1348:
1349: /** The new target */
1350: private IVariableBinding fTarget = null;
1351:
1352: /** The name of the new target */
1353: private String fTargetName;
1354:
1355: /** Does the move method need a target node? */
1356: private boolean fTargetNode = true;
1357:
1358: /** The target type */
1359: private IType fTargetType = null;
1360:
1361: /** Should getter methods be used to resolve visibility issues? */
1362: private boolean fUseGetters = true;
1363:
1364: /** Should setter methods be used to resolve visibility issues? */
1365: private boolean fUseSetters = true;
1366:
1367: /**
1368: * Creates a new move instance method processor.
1369: *
1370: * @param method
1371: * the method to move, or <code>null</code> if invoked by
1372: * scripting
1373: * @param settings
1374: * the code generation settings to apply, or <code>null</code>
1375: * if invoked by scripting
1376: */
1377: public MoveInstanceMethodProcessor(final IMethod method,
1378: final CodeGenerationSettings settings) {
1379: fSettings = settings;
1380: fMethod = method;
1381: if (method != null)
1382: initialize(method);
1383: }
1384:
1385: /**
1386: * {@inheritDoc}
1387: */
1388: public boolean canEnableComment() {
1389: return true;
1390: }
1391:
1392: /**
1393: * {@inheritDoc}
1394: */
1395: public final boolean canEnableDelegateUpdating() {
1396: return true;
1397: }
1398:
1399: /**
1400: * Checks whether a method with the proposed name already exists in the
1401: * target type.
1402: *
1403: * @param monitor
1404: * the progress monitor to display progress
1405: * @param status
1406: * the status of the condition checking
1407: * @throws JavaModelException
1408: * if the declared methods of the target type could not be
1409: * retrieved
1410: */
1411: protected void checkConflictingMethod(
1412: final IProgressMonitor monitor,
1413: final RefactoringStatus status) throws JavaModelException {
1414: Assert.isNotNull(monitor);
1415: Assert.isNotNull(status);
1416: final IMethod[] methods = fTargetType.getMethods();
1417: try {
1418: monitor.beginTask("", methods.length); //$NON-NLS-1$
1419: monitor
1420: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1421: IMethod method = null;
1422: for (int index = 0; index < methods.length; index++) {
1423: method = methods[index];
1424: if (method.getElementName().equals(fMethodName)
1425: && method.getParameterTypes().length == fMethod
1426: .getParameterTypes().length - 1)
1427: status
1428: .merge(RefactoringStatus
1429: .createErrorStatus(
1430: Messages
1431: .format(
1432: RefactoringCoreMessages.MoveInstanceMethodProcessor_method_already_exists,
1433: new String[] {
1434: fMethodName,
1435: fTargetType
1436: .getElementName() }),
1437: JavaStatusContext
1438: .create(method)));
1439: monitor.worked(1);
1440: }
1441: if (fMethodName.equals(fTargetType.getElementName()))
1442: status
1443: .merge(RefactoringStatus
1444: .createFatalErrorStatus(
1445: Messages
1446: .format(
1447: RefactoringCoreMessages.MoveInstanceMethodProcessor_method_type_clash,
1448: fMethodName),
1449: JavaStatusContext
1450: .create(fTargetType)));
1451: } finally {
1452: monitor.done();
1453: }
1454: }
1455:
1456: /**
1457: * Checks whether the new target name conflicts with an already existing
1458: * method parameter.
1459: *
1460: * @param monitor
1461: * the progress monitor to display progress
1462: * @param status
1463: * the status of the condition checking
1464: * @throws JavaModelException
1465: * if the method declaration of the method to move could not be
1466: * found
1467: */
1468: protected void checkConflictingTarget(
1469: final IProgressMonitor monitor,
1470: final RefactoringStatus status) throws JavaModelException {
1471: Assert.isNotNull(monitor);
1472: Assert.isNotNull(status);
1473: final MethodDeclaration declaration = ASTNodeSearchUtil
1474: .getMethodDeclarationNode(fMethod, fSourceRewrite
1475: .getRoot());
1476: VariableDeclaration variable = null;
1477: final List parameters = declaration.parameters();
1478: try {
1479: monitor.beginTask("", parameters.size()); //$NON-NLS-1$
1480: monitor
1481: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1482: for (final Iterator iterator = parameters.iterator(); iterator
1483: .hasNext();) {
1484: variable = (VariableDeclaration) iterator.next();
1485: if (fTargetName.equals(variable.getName()
1486: .getIdentifier())) {
1487: status
1488: .merge(RefactoringStatus
1489: .createErrorStatus(
1490: RefactoringCoreMessages.MoveInstanceMethodProcessor_target_name_already_used,
1491: JavaStatusContext
1492: .create(fMethod)));
1493: break;
1494: }
1495: monitor.worked(1);
1496: }
1497: } finally {
1498: monitor.done();
1499: }
1500: }
1501:
1502: /*
1503: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor,
1504: * org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
1505: */
1506: public final RefactoringStatus checkFinalConditions(
1507: final IProgressMonitor monitor,
1508: final CheckConditionsContext context) throws CoreException,
1509: OperationCanceledException {
1510: Assert.isNotNull(monitor);
1511: Assert.isNotNull(context);
1512: Assert.isNotNull(fTarget);
1513: final RefactoringStatus status = new RefactoringStatus();
1514: fChangeManager = new TextChangeManager();
1515: try {
1516: monitor.beginTask("", 4); //$NON-NLS-1$
1517: monitor
1518: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1519: status.merge(Checks.checkIfCuBroken(fMethod));
1520: if (!status.hasError()) {
1521: checkGenericTarget(new SubProgressMonitor(monitor, 1),
1522: status);
1523: if (status.isOK()) {
1524: final IType type = getTargetType();
1525: if (type != null) {
1526: if (type.isBinary() || type.isReadOnly()
1527: || !fMethod.exists()
1528: || fMethod.isBinary()
1529: || fMethod.isReadOnly())
1530: status
1531: .merge(RefactoringStatus
1532: .createFatalErrorStatus(
1533: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_binary,
1534: JavaStatusContext
1535: .create(fMethod)));
1536: else {
1537: status.merge(Checks.checkIfCuBroken(type));
1538: if (!status.hasError()) {
1539: if (!type.exists() || type.isBinary()
1540: || type.isReadOnly())
1541: status
1542: .merge(RefactoringStatus
1543: .createFatalErrorStatus(
1544: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_binary,
1545: JavaStatusContext
1546: .create(fMethod)));
1547: checkConflictingTarget(
1548: new SubProgressMonitor(monitor,
1549: 1), status);
1550: checkConflictingMethod(
1551: new SubProgressMonitor(monitor,
1552: 1), status);
1553: status
1554: .merge(Checks
1555: .validateModifiesFiles(
1556: computeModifiedFiles(
1557: fMethod
1558: .getCompilationUnit(),
1559: type
1560: .getCompilationUnit()),
1561: null));
1562: monitor.worked(1);
1563: if (!status.hasFatalError())
1564: fChangeManager = createChangeManager(
1565: status,
1566: new SubProgressMonitor(
1567: monitor, 1));
1568: }
1569: }
1570: } else
1571: status
1572: .merge(RefactoringStatus
1573: .createFatalErrorStatus(
1574: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_resolved_target,
1575: JavaStatusContext
1576: .create(fMethod)));
1577: }
1578: }
1579: } finally {
1580: monitor.done();
1581: }
1582: return status;
1583: }
1584:
1585: /**
1586: * Checks whether the target is a type variable or a generic type.
1587: *
1588: * @param monitor
1589: * the progress monitor to display progress
1590: * @param status
1591: * the refactoring status
1592: */
1593: protected void checkGenericTarget(final IProgressMonitor monitor,
1594: final RefactoringStatus status) {
1595: Assert.isNotNull(monitor);
1596: Assert.isNotNull(status);
1597: try {
1598: monitor.beginTask("", 1); //$NON-NLS-1$
1599: monitor
1600: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1601: final ITypeBinding binding = fTarget.getType();
1602: if (binding == null || binding.isTypeVariable())
1603: status
1604: .merge(RefactoringStatus
1605: .createFatalErrorStatus(
1606: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_generic_targets,
1607: JavaStatusContext
1608: .create(fMethod)));
1609: } finally {
1610: monitor.done();
1611: }
1612: }
1613:
1614: /**
1615: * Checks whether the method has references to type variables or generic
1616: * types.
1617: *
1618: * @param monitor
1619: * the progress monitor to display progress
1620: * @param declaration
1621: * the method declaration to check for generic types
1622: * @param status
1623: * the status of the condition checking
1624: */
1625: protected void checkGenericTypes(final IProgressMonitor monitor,
1626: final MethodDeclaration declaration,
1627: final RefactoringStatus status) {
1628: Assert.isNotNull(monitor);
1629: Assert.isNotNull(declaration);
1630: Assert.isNotNull(status);
1631: try {
1632: monitor.beginTask("", 1); //$NON-NLS-1$
1633: monitor
1634: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1635: final AstNodeFinder finder = new GenericReferenceFinder(
1636: declaration);
1637: declaration.accept(finder);
1638: if (!finder.getStatus().isOK())
1639: status.merge(finder.getStatus());
1640: } finally {
1641: monitor.done();
1642: }
1643: }
1644:
1645: /*
1646: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
1647: */
1648: public final RefactoringStatus checkInitialConditions(
1649: final IProgressMonitor monitor) throws CoreException,
1650: OperationCanceledException {
1651: Assert.isNotNull(monitor);
1652: final RefactoringStatus status = new RefactoringStatus();
1653: try {
1654: monitor.beginTask("", 4); //$NON-NLS-1$
1655: monitor
1656: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1657: status.merge(Checks.checkIfCuBroken(fMethod));
1658: if (!status.hasError()) {
1659: checkMethodDeclaration(new SubProgressMonitor(monitor,
1660: 1), status);
1661: if (status.isOK()) {
1662: final MethodDeclaration declaration = ASTNodeSearchUtil
1663: .getMethodDeclarationNode(fMethod,
1664: fSourceRewrite.getRoot());
1665: checkGenericTypes(
1666: new SubProgressMonitor(monitor, 1),
1667: declaration, status);
1668: checkMethodBody(new SubProgressMonitor(monitor, 1),
1669: declaration, status);
1670: checkPossibleTargets(new SubProgressMonitor(
1671: monitor, 1), declaration, status);
1672: }
1673: }
1674: } finally {
1675: monitor.done();
1676: }
1677: return status;
1678: }
1679:
1680: /**
1681: * Checks whether the instance method body is compatible with this
1682: * refactoring.
1683: *
1684: * @param monitor
1685: * the progress monitor to display progress
1686: * @param declaration
1687: * the method declaration whose body to check
1688: * @param status
1689: * the status of the condition checking
1690: */
1691: protected void checkMethodBody(final IProgressMonitor monitor,
1692: final MethodDeclaration declaration,
1693: final RefactoringStatus status) {
1694: Assert.isNotNull(monitor);
1695: Assert.isNotNull(declaration);
1696: Assert.isNotNull(status);
1697: try {
1698: monitor.beginTask("", 3); //$NON-NLS-1$
1699: monitor
1700: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1701: AstNodeFinder finder = new SuperReferenceFinder();
1702: declaration.accept(finder);
1703: if (!finder.getStatus().isOK())
1704: status.merge(finder.getStatus());
1705: monitor.worked(1);
1706: finder = null;
1707: final IMethodBinding binding = declaration.resolveBinding();
1708: if (binding != null) {
1709: final ITypeBinding declaring = binding
1710: .getDeclaringClass();
1711: if (declaring != null)
1712: finder = new EnclosingInstanceReferenceFinder(
1713: declaring);
1714: }
1715: if (finder != null) {
1716: declaration.accept(finder);
1717: if (!finder.getStatus().isOK())
1718: status.merge(finder.getStatus());
1719: monitor.worked(1);
1720: finder = new RecursiveCallFinder(declaration);
1721: declaration.accept(finder);
1722: if (!finder.getStatus().isOK())
1723: status.merge(finder.getStatus());
1724: monitor.worked(1);
1725: }
1726: } finally {
1727: monitor.done();
1728: }
1729: }
1730:
1731: /**
1732: * Checks whether the instance method declaration is compatible with this
1733: * refactoring.
1734: *
1735: * @param monitor
1736: * the progress monitor to display progress
1737: * @param status
1738: * the status of the condition checking
1739: * @throws JavaModelException
1740: * if the method does not exist
1741: */
1742: protected void checkMethodDeclaration(
1743: final IProgressMonitor monitor,
1744: final RefactoringStatus status) throws JavaModelException {
1745: Assert.isNotNull(monitor);
1746: Assert.isNotNull(status);
1747: try {
1748: monitor.beginTask("", 5); //$NON-NLS-1$
1749: monitor
1750: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1751: final int flags = fMethod.getFlags();
1752: if (Flags.isStatic(flags))
1753: status
1754: .merge(RefactoringStatus
1755: .createFatalErrorStatus(
1756: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_static_methods,
1757: JavaStatusContext
1758: .create(fMethod)));
1759: else if (Flags.isAbstract(flags))
1760: status
1761: .merge(RefactoringStatus
1762: .createFatalErrorStatus(
1763: RefactoringCoreMessages.MoveInstanceMethodProcessor_single_implementation,
1764: JavaStatusContext
1765: .create(fMethod)));
1766: monitor.worked(1);
1767: if (Flags.isNative(flags))
1768: status
1769: .merge(RefactoringStatus
1770: .createFatalErrorStatus(
1771: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_native_methods,
1772: JavaStatusContext
1773: .create(fMethod)));
1774: monitor.worked(1);
1775: if (Flags.isSynchronized(flags))
1776: status
1777: .merge(RefactoringStatus
1778: .createFatalErrorStatus(
1779: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_synchronized_methods,
1780: JavaStatusContext
1781: .create(fMethod)));
1782: monitor.worked(1);
1783: if (fMethod.isConstructor())
1784: status
1785: .merge(RefactoringStatus
1786: .createFatalErrorStatus(
1787: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_constructors,
1788: JavaStatusContext
1789: .create(fMethod)));
1790: monitor.worked(1);
1791: if (fMethod.getDeclaringType().isAnnotation())
1792: status
1793: .merge(RefactoringStatus
1794: .createFatalErrorStatus(
1795: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_annotation,
1796: JavaStatusContext
1797: .create(fMethod)));
1798: else if (fMethod.getDeclaringType().isInterface())
1799: status
1800: .merge(RefactoringStatus
1801: .createFatalErrorStatus(
1802: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_interface,
1803: JavaStatusContext
1804: .create(fMethod)));
1805: monitor.worked(1);
1806: } finally {
1807: monitor.done();
1808: }
1809: }
1810:
1811: /**
1812: * Checks whether the method has possible targets to be moved to
1813: *
1814: * @param monitor
1815: * the progress monitor to display progress
1816: * @param declaration
1817: * the method declaration to check
1818: * @param status
1819: * the status of the condition checking
1820: */
1821: protected void checkPossibleTargets(final IProgressMonitor monitor,
1822: final MethodDeclaration declaration,
1823: final RefactoringStatus status) {
1824: Assert.isNotNull(monitor);
1825: Assert.isNotNull(declaration);
1826: Assert.isNotNull(status);
1827: try {
1828: monitor.beginTask("", 1); //$NON-NLS-1$
1829: monitor
1830: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1831: if (computeTargetCategories(declaration).length < 1)
1832: status
1833: .merge(RefactoringStatus
1834: .createFatalErrorStatus(
1835: RefactoringCoreMessages.MoveInstanceMethodProcessor_cannot_be_moved,
1836: JavaStatusContext
1837: .create(fMethod)));
1838: } finally {
1839: monitor.done();
1840: }
1841: }
1842:
1843: /**
1844: * Searches for references to the original method.
1845: *
1846: * @param monitor
1847: * the progress monitor to use
1848: * @param status
1849: * the refactoring status to use
1850: * @return the array of search result groups
1851: * @throws CoreException
1852: * if an error occurred during search
1853: */
1854: protected SearchResultGroup[] computeMethodReferences(
1855: final IProgressMonitor monitor,
1856: final RefactoringStatus status) throws CoreException {
1857: Assert.isNotNull(monitor);
1858: Assert.isNotNull(status);
1859: try {
1860: monitor.beginTask("", 1); //$NON-NLS-1$
1861: monitor
1862: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_checking);
1863: final RefactoringSearchEngine2 engine = new RefactoringSearchEngine2(
1864: SearchPattern.createPattern(fMethod,
1865: IJavaSearchConstants.REFERENCES,
1866: SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
1867: engine.setStatus(status);
1868: engine.searchPattern(new SubProgressMonitor(monitor, 1));
1869: return (SearchResultGroup[]) engine.getResults();
1870: } finally {
1871: monitor.done();
1872: }
1873: }
1874:
1875: /**
1876: * Computes the files that are being modified by this refactoring.
1877: *
1878: * @param source
1879: * the source compilation unit
1880: * @param target
1881: * the target compilation unit
1882: * @return the modified files
1883: */
1884: protected IFile[] computeModifiedFiles(
1885: final ICompilationUnit source, final ICompilationUnit target) {
1886: Assert.isNotNull(source);
1887: Assert.isNotNull(target);
1888: if (source.equals(target))
1889: return ResourceUtil
1890: .getFiles(new ICompilationUnit[] { source });
1891: return ResourceUtil.getFiles(new ICompilationUnit[] { source,
1892: target });
1893: }
1894:
1895: /**
1896: * Returns the reserved identifiers in the method to move.
1897: *
1898: * @return the reserved identifiers
1899: * @throws JavaModelException
1900: * if the method declaration could not be found
1901: */
1902: protected String[] computeReservedIdentifiers()
1903: throws JavaModelException {
1904: final List names = new ArrayList();
1905: final MethodDeclaration declaration = ASTNodeSearchUtil
1906: .getMethodDeclarationNode(fMethod, fSourceRewrite
1907: .getRoot());
1908: if (declaration != null) {
1909: final List parameters = declaration.parameters();
1910: VariableDeclaration variable = null;
1911: for (int index = 0; index < parameters.size(); index++) {
1912: variable = (VariableDeclaration) parameters.get(index);
1913: names.add(variable.getName().getIdentifier());
1914: }
1915: final Block body = declaration.getBody();
1916: if (body != null) {
1917: final IBinding[] bindings = new ScopeAnalyzer(
1918: fSourceRewrite.getRoot()).getDeclarationsAfter(
1919: body.getStartPosition(),
1920: ScopeAnalyzer.VARIABLES);
1921: for (int index = 0; index < bindings.length; index++)
1922: names.add(bindings[index].getName());
1923: }
1924: }
1925: final String[] result = new String[names.size()];
1926: names.toArray(result);
1927: return result;
1928: }
1929:
1930: /**
1931: * Computes the target categories for the method to move.
1932: *
1933: * @param declaration
1934: * the method declaration
1935: * @return the possible targets as variable bindings of read-only fields and
1936: * parameters
1937: */
1938: protected IVariableBinding[] computeTargetCategories(
1939: final MethodDeclaration declaration) {
1940: Assert.isNotNull(declaration);
1941: if (fPossibleTargets.length == 0
1942: || fCandidateTargets.length == 0) {
1943: final List possibleTargets = new ArrayList(16);
1944: final List candidateTargets = new ArrayList(16);
1945: final IMethodBinding method = declaration.resolveBinding();
1946: if (method != null) {
1947: final ITypeBinding declaring = method
1948: .getDeclaringClass();
1949: IVariableBinding[] bindings = getArgumentBindings(declaration);
1950: ITypeBinding binding = null;
1951: for (int index = 0; index < bindings.length; index++) {
1952: binding = bindings[index].getType();
1953: if ((binding.isClass() || binding.isEnum())
1954: && binding.isFromSource()) {
1955: possibleTargets.add(bindings[index]);
1956: candidateTargets.add(bindings[index]);
1957: }
1958: }
1959: final ReadyOnlyFieldFinder visitor = new ReadyOnlyFieldFinder(
1960: declaring);
1961: declaration.accept(visitor);
1962: bindings = visitor.getReadOnlyFields();
1963: for (int index = 0; index < bindings.length; index++) {
1964: binding = bindings[index].getType();
1965: if (binding.isClass() && binding.isFromSource())
1966: possibleTargets.add(bindings[index]);
1967: }
1968: bindings = visitor.getDeclaredFields();
1969: for (int index = 0; index < bindings.length; index++) {
1970: binding = bindings[index].getType();
1971: if (binding.isClass() && binding.isFromSource())
1972: candidateTargets.add(bindings[index]);
1973: }
1974: }
1975: fPossibleTargets = new IVariableBinding[possibleTargets
1976: .size()];
1977: possibleTargets.toArray(fPossibleTargets);
1978: fCandidateTargets = new IVariableBinding[candidateTargets
1979: .size()];
1980: candidateTargets.toArray(fCandidateTargets);
1981: }
1982: return fPossibleTargets;
1983: }
1984:
1985: /**
1986: * Creates a visibility-adjusted target expression taking advantage of
1987: * existing accessor methods.
1988: *
1989: * @param enclosingElement
1990: * the java element which encloses the current method access.
1991: * @param expression
1992: * the expression to access the target, or <code>null</code>
1993: * @param adjustments
1994: * the map of elements to visibility adjustments
1995: * @param rewrite
1996: * the ast rewrite to use
1997: * @return an adjusted target expression, or <code>null</code> if the
1998: * access did not have to be changed
1999: * @throws JavaModelException
2000: * if an error occurs while accessing the target expression
2001: */
2002: protected Expression createAdjustedTargetExpression(
2003: final IJavaElement enclosingElement,
2004: final Expression expression, final Map adjustments,
2005: final ASTRewrite rewrite) throws JavaModelException {
2006: Assert.isNotNull(enclosingElement);
2007: Assert.isNotNull(adjustments);
2008: Assert.isNotNull(rewrite);
2009: final IJavaElement element = fTarget.getJavaElement();
2010: if (element != null
2011: && !Modifier.isPublic(fTarget.getModifiers())) {
2012: final IField field = (IField) fTarget.getJavaElement();
2013: if (field != null) {
2014: boolean same = field
2015: .getAncestor(IJavaElement.PACKAGE_FRAGMENT)
2016: .equals(
2017: enclosingElement
2018: .getAncestor(IJavaElement.PACKAGE_FRAGMENT));
2019: final Modifier.ModifierKeyword keyword = same ? null
2020: : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
2021: final String modifier = same ? RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_default
2022: : RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_public;
2023: if (fUseGetters) {
2024: final IMethod getter = GetterSetterUtil
2025: .getGetter(field);
2026: if (getter != null) {
2027: final MethodDeclaration method = ASTNodeSearchUtil
2028: .getMethodDeclarationNode(getter,
2029: fSourceRewrite.getRoot());
2030: if (method != null) {
2031: final IMethodBinding binding = method
2032: .resolveBinding();
2033: if (binding != null
2034: && MemberVisibilityAdjustor
2035: .hasLowerVisibility(
2036: getter.getFlags(),
2037: same ? Modifier.NONE
2038: : (keyword == null ? Modifier.NONE
2039: : keyword
2040: .toFlagValue()))
2041: && MemberVisibilityAdjustor
2042: .needsVisibilityAdjustments(
2043: getter, keyword,
2044: adjustments))
2045: adjustments
2046: .put(
2047: getter,
2048: new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(
2049: getter,
2050: keyword,
2051: RefactoringStatus
2052: .createWarningStatus(
2053: Messages
2054: .format(
2055: RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning,
2056: new String[] {
2057: BindingLabelProvider
2058: .getBindingLabel(
2059: binding,
2060: JavaElementLabels.ALL_FULLY_QUALIFIED),
2061: modifier }),
2062: JavaStatusContext
2063: .create(getter))));
2064: final MethodInvocation invocation = rewrite
2065: .getAST().newMethodInvocation();
2066: invocation.setExpression(expression);
2067: invocation.setName(rewrite.getAST()
2068: .newSimpleName(
2069: getter.getElementName()));
2070: return invocation;
2071: }
2072: }
2073: }
2074: if (MemberVisibilityAdjustor.hasLowerVisibility(field
2075: .getFlags(), (keyword == null ? Modifier.NONE
2076: : keyword.toFlagValue()))
2077: && MemberVisibilityAdjustor
2078: .needsVisibilityAdjustments(field,
2079: keyword, adjustments))
2080: adjustments
2081: .put(
2082: field,
2083: new MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment(
2084: field,
2085: keyword,
2086: RefactoringStatus
2087: .createWarningStatus(
2088: Messages
2089: .format(
2090: RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_field_warning,
2091: new String[] {
2092: BindingLabelProvider
2093: .getBindingLabel(
2094: fTarget,
2095: JavaElementLabels.ALL_FULLY_QUALIFIED),
2096: modifier }),
2097: JavaStatusContext
2098: .create(field))));
2099: }
2100: }
2101: return null;
2102: }
2103:
2104: /**
2105: * Creates a generic argument list of the refactored moved method
2106: *
2107: * @param declaration
2108: * the method declaration of the method to move
2109: * @param arguments
2110: * the argument list to create
2111: * @param factory
2112: * the argument factory to use
2113: * @return <code>true</code> if a target node had to be inserted as first
2114: * argument, <code>false</code> otherwise
2115: * @throws JavaModelException
2116: * if an error occurs
2117: */
2118: protected boolean createArgumentList(
2119: final MethodDeclaration declaration, final List arguments,
2120: final IArgumentFactory factory) throws JavaModelException {
2121: Assert.isNotNull(declaration);
2122: Assert.isNotNull(arguments);
2123: Assert.isNotNull(factory);
2124: final AstNodeFinder finder = new ThisReferenceFinder();
2125: declaration.accept(finder);
2126: IVariableBinding binding = null;
2127: VariableDeclaration variable = null;
2128: boolean added = false;
2129: final int size = declaration.parameters().size();
2130: for (int index = 0; index < size; index++) {
2131: variable = (VariableDeclaration) declaration.parameters()
2132: .get(index);
2133: binding = variable.resolveBinding();
2134: if (binding != null) {
2135: if (!Bindings.equals(binding, fTarget))
2136: arguments.add(factory.getArgumentNode(binding,
2137: index == size - 1));
2138: else if (!finder.getStatus().isOK()) {
2139: arguments.add(factory.getTargetNode());
2140: added = true;
2141: }
2142: } else
2143: arguments.add(factory.getArgumentNode(binding,
2144: index == size - 1));
2145: }
2146: if (!finder.getStatus().isOK() && !added) {
2147: arguments.add(0, factory.getTargetNode());
2148: added = true;
2149: }
2150: return added;
2151: }
2152:
2153: /*
2154: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#createChange(org.eclipse.core.runtime.IProgressMonitor)
2155: */
2156: public final Change createChange(final IProgressMonitor monitor)
2157: throws CoreException, OperationCanceledException {
2158: Assert.isNotNull(monitor);
2159: try {
2160: monitor.beginTask("", 6); //$NON-NLS-1$
2161: monitor
2162: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
2163: final TextChange[] changes = fChangeManager.getAllChanges();
2164: if (changes.length == 1)
2165: return changes[0];
2166: final List list = new ArrayList(changes.length);
2167: list.addAll(Arrays.asList(changes));
2168: final Map arguments = new HashMap();
2169: String project = null;
2170: final IJavaProject javaProject = fMethod.getJavaProject();
2171: if (javaProject != null)
2172: project = javaProject.getElementName();
2173: int flags = JavaRefactoringDescriptor.JAR_REFACTORING
2174: | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT
2175: | RefactoringDescriptor.STRUCTURAL_CHANGE
2176: | RefactoringDescriptor.MULTI_CHANGE;
2177: final IType declaring = fMethod.getDeclaringType();
2178: try {
2179: if (declaring.isAnonymous() || declaring.isLocal())
2180: flags |= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
2181: } catch (JavaModelException exception) {
2182: JavaPlugin.log(exception);
2183: }
2184: final String description = Messages
2185: .format(
2186: RefactoringCoreMessages.MoveInstanceMethodProcessor_descriptor_description_short,
2187: fMethod.getElementName());
2188: final String header = Messages
2189: .format(
2190: RefactoringCoreMessages.MoveInstanceMethodProcessor_descriptor_description,
2191: new String[] {
2192: JavaElementLabels
2193: .getElementLabel(
2194: fMethod,
2195: JavaElementLabels.ALL_FULLY_QUALIFIED),
2196: BindingLabelProvider
2197: .getBindingLabel(
2198: fTarget,
2199: JavaElementLabels.ALL_FULLY_QUALIFIED) });
2200: final JDTRefactoringDescriptorComment comment = new JDTRefactoringDescriptorComment(
2201: project, this , header);
2202: comment
2203: .addSetting(Messages
2204: .format(
2205: RefactoringCoreMessages.MoveInstanceMethodProcessor_moved_element_pattern,
2206: RefactoringCoreMessages.JavaRefactoringDescriptor_not_available));
2207: comment
2208: .addSetting(Messages
2209: .format(
2210: RefactoringCoreMessages.MoveInstanceMethodProcessor_target_element_pattern,
2211: BindingLabelProvider
2212: .getBindingLabel(
2213: fTarget,
2214: JavaElementLabels.ALL_FULLY_QUALIFIED)));
2215: comment
2216: .addSetting(Messages
2217: .format(
2218: RefactoringCoreMessages.MoveInstanceMethodProcessor_method_name_pattern,
2219: getMethodName()));
2220: if (needsTargetNode())
2221: comment
2222: .addSetting(Messages
2223: .format(
2224: RefactoringCoreMessages.MoveInstanceMethodProcessor_parameter_name_pattern,
2225: getTargetName()));
2226: final MoveMethodDescriptor descriptor = new MoveMethodDescriptor(
2227: project, description, comment.asString(),
2228: arguments, flags);
2229: arguments.put(
2230: JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT,
2231: JavaRefactoringDescriptorUtil.elementToHandle(
2232: project, fMethod));
2233: arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME,
2234: fMethodName);
2235: arguments.put(ATTRIBUTE_TARGET_NAME, fTargetName);
2236: arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(
2237: fDelegateDeprecation).toString());
2238: arguments.put(ATTRIBUTE_REMOVE, Boolean.valueOf(fRemove)
2239: .toString());
2240: arguments.put(ATTRIBUTE_INLINE, Boolean.valueOf(fInline)
2241: .toString());
2242: arguments.put(ATTRIBUTE_USE_GETTER, Boolean.valueOf(
2243: fUseGetters).toString());
2244: arguments.put(ATTRIBUTE_USE_SETTER, Boolean.valueOf(
2245: fUseSetters).toString());
2246: arguments.put(ATTRIBUTE_TARGET_INDEX, new Integer(
2247: getTargetIndex()).toString());
2248: return new DynamicValidationRefactoringChange(
2249: descriptor,
2250: RefactoringCoreMessages.MoveInstanceMethodRefactoring_name,
2251: (Change[]) list.toArray(new Change[list.size()]));
2252: } finally {
2253: monitor.done();
2254: }
2255: }
2256:
2257: /**
2258: * Creates the text change manager for this processor.
2259: *
2260: * @param status
2261: * the refactoring status
2262: * @param monitor
2263: * the progress monitor to display progress
2264: * @return the created text change manager
2265: * @throws JavaModelException
2266: * if the method declaration could not be found
2267: * @throws CoreException
2268: * if the changes could not be generated
2269: */
2270: protected TextChangeManager createChangeManager(
2271: final RefactoringStatus status,
2272: final IProgressMonitor monitor) throws JavaModelException,
2273: CoreException {
2274: Assert.isNotNull(status);
2275: Assert.isNotNull(monitor);
2276: try {
2277: monitor.beginTask("", 7); //$NON-NLS-1$
2278: monitor
2279: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
2280: fSourceRewrite.clearASTAndImportRewrites();
2281: final TextChangeManager manager = new TextChangeManager();
2282: final CompilationUnitRewrite targetRewrite = fMethod
2283: .getCompilationUnit().equals(
2284: getTargetType().getCompilationUnit()) ? fSourceRewrite
2285: : new CompilationUnitRewrite(getTargetType()
2286: .getCompilationUnit());
2287: final MethodDeclaration declaration = ASTNodeSearchUtil
2288: .getMethodDeclarationNode(fMethod, fSourceRewrite
2289: .getRoot());
2290: final SearchResultGroup[] references = computeMethodReferences(
2291: new SubProgressMonitor(monitor, 1), status);
2292: final Map rewrites = new HashMap(2);
2293: rewrites.put(fSourceRewrite.getCu(), fSourceRewrite);
2294: if (!fSourceRewrite.getCu().equals(targetRewrite.getCu()))
2295: rewrites.put(targetRewrite.getCu(), targetRewrite);
2296: final ASTRewrite sourceRewrite = ASTRewrite
2297: .create(fSourceRewrite.getRoot().getAST());
2298: final MemberVisibilityAdjustor adjustor = new MemberVisibilityAdjustor(
2299: fTargetType, fMethod);
2300: adjustor.setStatus(status);
2301: adjustor.setVisibilitySeverity(RefactoringStatus.WARNING);
2302: adjustor.setFailureSeverity(RefactoringStatus.WARNING);
2303: adjustor.setRewrites(rewrites);
2304: adjustor
2305: .setRewrite(sourceRewrite, fSourceRewrite.getRoot());
2306: adjustor
2307: .adjustVisibility(new SubProgressMonitor(monitor, 1));
2308: final IDocument document = new Document(fMethod
2309: .getCompilationUnit().getBuffer().getContents());
2310: final boolean target = createMethodCopy(document,
2311: declaration, sourceRewrite, rewrites, adjustor
2312: .getAdjustments(), status,
2313: new SubProgressMonitor(monitor, 1));
2314: createMethodJavadocReferences(rewrites, declaration,
2315: references, target, status, new SubProgressMonitor(
2316: monitor, 1));
2317: if (!fSourceRewrite.getCu().equals(targetRewrite.getCu()))
2318: createMethodImports(targetRewrite, declaration,
2319: new SubProgressMonitor(monitor, 1), status);
2320: boolean removable = false;
2321: if (fInline) {
2322: removable = createMethodDelegator(rewrites,
2323: declaration, references, adjustor
2324: .getAdjustments(), target, status,
2325: new SubProgressMonitor(monitor, 1));
2326: if (fRemove && removable) {
2327: fSourceRewrite
2328: .getASTRewrite()
2329: .remove(
2330: declaration,
2331: fSourceRewrite
2332: .createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_remove_original_method));
2333: if (!fSourceRewrite.getCu().equals(
2334: fTargetType.getCompilationUnit()))
2335: fSourceRewrite.getImportRemover()
2336: .registerRemovedNode(declaration);
2337: }
2338: }
2339: if (!fRemove || !removable)
2340: createMethodDelegation(declaration, rewrites, adjustor
2341: .getAdjustments(), status,
2342: new SubProgressMonitor(monitor, 1));
2343:
2344: // Do not adjust visibility of a target field; references to the
2345: // field will be removed anyway.
2346: final IJavaElement targetElement = fTarget.getJavaElement();
2347: if (targetElement != null
2348: && targetElement instanceof IField
2349: && (Flags.isPrivate(fMethod.getFlags()) || !fInline)) {
2350: final IVisibilityAdjustment adjustmentForTarget = (IVisibilityAdjustment) adjustor
2351: .getAdjustments().get(targetElement);
2352: if (adjustmentForTarget != null)
2353: adjustor.getAdjustments().remove(targetElement);
2354: }
2355:
2356: adjustor.rewriteVisibility(new SubProgressMonitor(monitor,
2357: 1));
2358: sourceRewrite.rewriteAST(document, fMethod.getJavaProject()
2359: .getOptions(true));
2360: createMethodSignature(document, declaration, sourceRewrite,
2361: rewrites);
2362: ICompilationUnit unit = null;
2363: CompilationUnitRewrite rewrite = null;
2364: for (final Iterator iterator = rewrites.keySet().iterator(); iterator
2365: .hasNext();) {
2366: unit = (ICompilationUnit) iterator.next();
2367: rewrite = (CompilationUnitRewrite) rewrites.get(unit);
2368: manager.manage(unit, rewrite.createChange());
2369: }
2370: return manager;
2371: } finally {
2372: monitor.done();
2373: }
2374: }
2375:
2376: /**
2377: * Creates the necessary change to inline a method invocation represented by
2378: * a search match.
2379: *
2380: * @param rewriter
2381: * the current compilation unit rewrite
2382: * @param declaration
2383: * the source method declaration
2384: * @param match
2385: * the search match representing the method invocation
2386: * @param adjustments
2387: * the map of elements to visibility adjustments
2388: * @param target
2389: * <code>true</code> if a target node had to be inserted as
2390: * first argument, <code>false</code> otherwise
2391: * @param status
2392: * the refactoring status
2393: * @return <code>true</code> if the inline change could be performed,
2394: * <code>false</code> otherwise
2395: * @throws JavaModelException
2396: * if a problem occurred while creating the inlined target
2397: * expression for field targets
2398: */
2399: protected boolean createInlinedMethodInvocation(
2400: final CompilationUnitRewrite rewriter,
2401: final MethodDeclaration declaration,
2402: final SearchMatch match, final Map adjustments,
2403: final boolean target, final RefactoringStatus status)
2404: throws JavaModelException {
2405: Assert.isNotNull(rewriter);
2406: Assert.isNotNull(declaration);
2407: Assert.isNotNull(match);
2408: Assert.isNotNull(adjustments);
2409: Assert.isNotNull(status);
2410: boolean result = true;
2411: final ASTRewrite rewrite = rewriter.getASTRewrite();
2412: final ASTNode node = ASTNodeSearchUtil.findNode(match, rewriter
2413: .getRoot());
2414: final TextEditGroup group = rewriter
2415: .createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_method_invocation);
2416: if (node instanceof MethodInvocation) {
2417: final MethodInvocation invocation = (MethodInvocation) node;
2418: final ListRewrite list = rewrite.getListRewrite(invocation,
2419: MethodInvocation.ARGUMENTS_PROPERTY);
2420: if (fTarget.isField()) {
2421: Expression access = null;
2422: if (invocation.getExpression() != null) {
2423: access = createInlinedTargetExpression(rewriter,
2424: (IJavaElement) match.getElement(),
2425: invocation.getExpression(), adjustments,
2426: status);
2427: rewrite.set(invocation,
2428: MethodInvocation.EXPRESSION_PROPERTY,
2429: access, group);
2430: } else
2431: rewrite.set(invocation,
2432: MethodInvocation.EXPRESSION_PROPERTY,
2433: rewrite.getAST().newSimpleName(
2434: fTarget.getName()), group);
2435: if (target) {
2436: if (access == null
2437: || !(access instanceof FieldAccess))
2438: list.insertFirst(rewrite.getAST()
2439: .newThisExpression(), null);
2440: else
2441: list.insertLast(rewrite
2442: .createCopyTarget(invocation
2443: .getExpression()), null);
2444: }
2445: } else {
2446: final IVariableBinding[] bindings = getArgumentBindings(declaration);
2447: if (bindings.length > 0) {
2448: int index = 0;
2449: for (; index < bindings.length; index++)
2450: if (Bindings.equals(bindings[index], fTarget))
2451: break;
2452: if (index < bindings.length
2453: && invocation.arguments().size() > index) {
2454: final Expression argument = (Expression) invocation
2455: .arguments().get(index);
2456: if (argument instanceof NullLiteral) {
2457: status
2458: .merge(RefactoringStatus
2459: .createErrorStatus(
2460: Messages
2461: .format(
2462: RefactoringCoreMessages.MoveInstanceMethodProcessor_no_null_argument,
2463: BindingLabelProvider
2464: .getBindingLabel(
2465: declaration
2466: .resolveBinding(),
2467: JavaElementLabels.ALL_FULLY_QUALIFIED)),
2468: JavaStatusContext
2469: .create(
2470: rewriter
2471: .getCu(),
2472: invocation)));
2473: result = false;
2474: } else {
2475: if (argument instanceof ThisExpression)
2476: rewrite.remove(invocation
2477: .getExpression(), null);
2478: else
2479: rewrite
2480: .set(
2481: invocation,
2482: MethodInvocation.EXPRESSION_PROPERTY,
2483: rewrite
2484: .createCopyTarget(argument),
2485: group);
2486: if (target) {
2487: if (invocation.getExpression() != null)
2488: list
2489: .replace(
2490: argument,
2491: rewrite
2492: .createCopyTarget(invocation
2493: .getExpression()),
2494: group);
2495: else {
2496: final ThisExpression expression = rewrite
2497: .getAST()
2498: .newThisExpression();
2499: final AbstractTypeDeclaration member = (AbstractTypeDeclaration) ASTNodes
2500: .getParent(
2501: invocation,
2502: AbstractTypeDeclaration.class);
2503: if (member != null) {
2504: final ITypeBinding resolved = member
2505: .resolveBinding();
2506: if (ASTNodes
2507: .getParent(
2508: invocation,
2509: AnonymousClassDeclaration.class) != null
2510: || (resolved != null && resolved
2511: .isMember())) {
2512: final IMethodBinding method = declaration
2513: .resolveBinding();
2514: if (method != null) {
2515: final ITypeBinding declaring = method
2516: .getDeclaringClass();
2517: if (declaring != null)
2518: expression
2519: .setQualifier(rewrite
2520: .getAST()
2521: .newSimpleName(
2522: declaring
2523: .getName()));
2524: }
2525: }
2526: }
2527: list.replace(argument, expression,
2528: group);
2529: }
2530: } else
2531: list.remove(argument, group);
2532: }
2533: }
2534: }
2535: }
2536: if (result)
2537: rewrite.set(invocation, MethodInvocation.NAME_PROPERTY,
2538: rewrite.getAST().newSimpleName(fMethodName),
2539: group);
2540: }
2541: return result;
2542: }
2543:
2544: /**
2545: * Creates the target field expression for the inline method invocation.
2546: *
2547: * @param rewriter
2548: * the current compilation unit rewrite
2549: * @param enclosingElement
2550: * the enclosing java element of the method invocation.
2551: * @param original
2552: * the original method invocation expression
2553: * @param adjustments
2554: * the map of elements to visibility adjustments
2555: * @param status
2556: * the refactoring status
2557: * @return
2558: * returns the target expression
2559: * @throws JavaModelException
2560: * if a problem occurred while retrieving potential getter
2561: * methods of the target
2562: */
2563: protected Expression createInlinedTargetExpression(
2564: final CompilationUnitRewrite rewriter,
2565: final IJavaElement enclosingElement,
2566: final Expression original, final Map adjustments,
2567: final RefactoringStatus status) throws JavaModelException {
2568: Assert.isNotNull(rewriter);
2569: Assert.isNotNull(enclosingElement);
2570: Assert.isNotNull(original);
2571: Assert.isNotNull(adjustments);
2572: Assert.isNotNull(status);
2573: Assert.isTrue(fTarget.isField());
2574: final Expression expression = (Expression) ASTNode.copySubtree(
2575: fSourceRewrite.getASTRewrite().getAST(), original);
2576: final Expression result = createAdjustedTargetExpression(
2577: enclosingElement, expression, adjustments,
2578: fSourceRewrite.getASTRewrite());
2579: if (result == null) {
2580: final FieldAccess access = fSourceRewrite.getASTRewrite()
2581: .getAST().newFieldAccess();
2582: access.setExpression(expression);
2583: access.setName(fSourceRewrite.getASTRewrite().getAST()
2584: .newSimpleName(fTarget.getName()));
2585: return access;
2586: }
2587: return result;
2588: }
2589:
2590: /**
2591: * Creates the method arguments for the target method declaration.
2592: *
2593: * @param rewrites
2594: * the compilation unit rewrites
2595: * @param rewrite
2596: * the source ast rewrite
2597: * @param declaration
2598: * the source method declaration
2599: * @param adjustments
2600: * the map of elements to visibility adjustments
2601: * @param status
2602: * the refactoring status
2603: * @return <code>true</code> if a target node had to be inserted as method
2604: * argument, <code>false</code> otherwise
2605: * @throws JavaModelException
2606: * if an error occurs while accessing the types of the arguments
2607: */
2608: protected boolean createMethodArguments(final Map rewrites,
2609: final ASTRewrite rewrite,
2610: final MethodDeclaration declaration, final Map adjustments,
2611: final RefactoringStatus status) throws JavaModelException {
2612: Assert.isNotNull(rewrites);
2613: Assert.isNotNull(declaration);
2614: Assert.isNotNull(rewrite);
2615: Assert.isNotNull(adjustments);
2616: Assert.isNotNull(status);
2617: final CompilationUnitRewrite rewriter = getCompilationUnitRewrite(
2618: rewrites, getTargetType().getCompilationUnit());
2619: final AST ast = rewriter.getRoot().getAST();
2620: final AstNodeFinder finder = new AnonymousClassReferenceFinder(
2621: declaration);
2622: declaration.accept(finder);
2623: final List arguments = new ArrayList(declaration.parameters()
2624: .size() + 1);
2625: final boolean result = createArgumentList(declaration,
2626: arguments, new VisibilityAdjustingArgumentFactory(ast,
2627: rewrites, adjustments) {
2628:
2629: public final ASTNode getArgumentNode(
2630: final IVariableBinding binding,
2631: final boolean last)
2632: throws JavaModelException {
2633: Assert.isNotNull(binding);
2634: final SingleVariableDeclaration variable = ast
2635: .newSingleVariableDeclaration();
2636: final ITypeBinding type = binding.getType();
2637: adjustTypeVisibility(type);
2638: variable.setName(ast.newSimpleName(binding
2639: .getName()));
2640: variable.modifiers().addAll(
2641: ast
2642: .newModifiers(binding
2643: .getModifiers()));
2644: final IMethodBinding method = binding
2645: .getDeclaringMethod();
2646: if (last && method != null
2647: && method.isVarargs()) {
2648: variable.setVarargs(true);
2649: String name = null;
2650: if (type.isArray()) {
2651: name = type.getElementType().getName();
2652: if (PrimitiveType.toCode(name) != null)
2653: variable
2654: .setType(ast
2655: .newPrimitiveType(PrimitiveType
2656: .toCode(name)));
2657: else
2658: variable
2659: .setType(ast
2660: .newSimpleType(ast
2661: .newSimpleName(name)));
2662: } else {
2663: name = type.getName();
2664: if (PrimitiveType.toCode(name) != null)
2665: variable
2666: .setType(ast
2667: .newPrimitiveType(PrimitiveType
2668: .toCode(name)));
2669: else
2670: variable
2671: .setType(ast
2672: .newSimpleType(ast
2673: .newSimpleName(name)));
2674: }
2675: } else
2676: variable.setType(rewriter
2677: .getImportRewrite().addImport(type,
2678: ast));
2679: return variable;
2680: }
2681:
2682: public final ASTNode getTargetNode()
2683: throws JavaModelException {
2684: final SingleVariableDeclaration variable = ast
2685: .newSingleVariableDeclaration();
2686: final IMethodBinding method = declaration
2687: .resolveBinding();
2688: if (method != null) {
2689: final ITypeBinding declaring = method
2690: .getDeclaringClass();
2691: if (declaring != null) {
2692: adjustTypeVisibility(declaring);
2693: variable.setType(rewriter
2694: .getImportRewrite().addImport(
2695: declaring, ast));
2696: variable.setName(ast
2697: .newSimpleName(fTargetName));
2698: if (finder.getResult().size() > 0)
2699: variable
2700: .modifiers()
2701: .add(
2702: ast
2703: .newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
2704: }
2705: }
2706: return variable;
2707: }
2708: });
2709: final ListRewrite list = rewrite.getListRewrite(declaration,
2710: MethodDeclaration.PARAMETERS_PROPERTY);
2711: ASTNode node = null;
2712: for (final Iterator iterator = declaration.parameters()
2713: .iterator(); iterator.hasNext();) {
2714: node = (ASTNode) iterator.next();
2715: list.remove(node, null);
2716: }
2717: for (final Iterator iterator = arguments.iterator(); iterator
2718: .hasNext();) {
2719: node = (ASTNode) iterator.next();
2720: list.insertLast(node, null);
2721: }
2722: return result;
2723: }
2724:
2725: /**
2726: * Creates the method body for the target method declaration.
2727: *
2728: * @param rewriter
2729: * the target compilation unit rewrite
2730: * @param rewrite
2731: * the source ast rewrite
2732: * @param declaration
2733: * the source method declaration
2734: */
2735: protected void createMethodBody(
2736: final CompilationUnitRewrite rewriter,
2737: final ASTRewrite rewrite,
2738: final MethodDeclaration declaration) {
2739: Assert.isNotNull(declaration);
2740: declaration.getBody().accept(
2741: new MethodBodyRewriter(rewriter, rewrite, declaration));
2742: }
2743:
2744: /**
2745: * Creates the method comment for the target method declaration.
2746: *
2747: * @param rewrite
2748: * the source ast rewrite
2749: * @param declaration
2750: * the source method declaration
2751: * @throws JavaModelException
2752: * if the argument references could not be generated
2753: */
2754: protected void createMethodComment(final ASTRewrite rewrite,
2755: final MethodDeclaration declaration)
2756: throws JavaModelException {
2757: Assert.isNotNull(rewrite);
2758: Assert.isNotNull(declaration);
2759: final Javadoc comment = declaration.getJavadoc();
2760: if (comment != null) {
2761: final List tags = new LinkedList(comment.tags());
2762: final IVariableBinding[] bindings = getArgumentBindings(declaration);
2763: final Map elements = new HashMap(bindings.length);
2764: String name = null;
2765: List fragments = null;
2766: TagElement element = null;
2767: TagElement reference = null;
2768: IVariableBinding binding = null;
2769: for (int index = 0; index < bindings.length; index++) {
2770: binding = bindings[index];
2771: for (final Iterator iterator = comment.tags()
2772: .iterator(); iterator.hasNext();) {
2773: element = (TagElement) iterator.next();
2774: name = element.getTagName();
2775: fragments = element.fragments();
2776: if (name != null) {
2777: if (name.equals(TagElement.TAG_PARAM)
2778: && !fragments.isEmpty()
2779: && fragments.get(0) instanceof SimpleName) {
2780: final SimpleName simple = (SimpleName) fragments
2781: .get(0);
2782: if (binding.getName().equals(
2783: simple.getIdentifier())) {
2784: elements.put(binding.getKey(), element);
2785: tags.remove(element);
2786: }
2787: } else if (reference == null)
2788: reference = element;
2789: }
2790: }
2791: }
2792: if (bindings.length == 0 && reference == null) {
2793: for (final Iterator iterator = comment.tags()
2794: .iterator(); iterator.hasNext();) {
2795: element = (TagElement) iterator.next();
2796: name = element.getTagName();
2797: fragments = element.fragments();
2798: if (name != null
2799: && !name.equals(TagElement.TAG_PARAM))
2800: reference = element;
2801: }
2802: }
2803: final List arguments = new ArrayList(bindings.length + 1);
2804: createArgumentList(declaration, arguments,
2805: new IArgumentFactory() {
2806:
2807: public final ASTNode getArgumentNode(
2808: final IVariableBinding argument,
2809: final boolean last)
2810: throws JavaModelException {
2811: Assert.isNotNull(argument);
2812: if (elements.containsKey(argument.getKey()))
2813: return rewrite
2814: .createCopyTarget((ASTNode) elements
2815: .get(argument.getKey()));
2816: return JavadocUtil.createParamTag(argument
2817: .getName(), declaration.getAST(),
2818: fMethod.getJavaProject());
2819: }
2820:
2821: public final ASTNode getTargetNode()
2822: throws JavaModelException {
2823: return JavadocUtil.createParamTag(
2824: fTargetName, declaration.getAST(),
2825: fMethod.getJavaProject());
2826: }
2827: });
2828: final ListRewrite rewriter = rewrite.getListRewrite(
2829: comment, Javadoc.TAGS_PROPERTY);
2830: ASTNode tag = null;
2831: for (final Iterator iterator = comment.tags().iterator(); iterator
2832: .hasNext();) {
2833: tag = (ASTNode) iterator.next();
2834: if (!tags.contains(tag))
2835: rewriter.remove(tag, null);
2836: }
2837: for (final Iterator iterator = arguments.iterator(); iterator
2838: .hasNext();) {
2839: tag = (ASTNode) iterator.next();
2840: if (reference != null)
2841: rewriter.insertBefore(tag, reference, null);
2842: else
2843: rewriter.insertLast(tag, null);
2844: }
2845: }
2846: }
2847:
2848: /**
2849: * Creates the method content of the moved method.
2850: *
2851: * @param document
2852: * the document representing the source compilation unit
2853: * @param declaration
2854: * the source method declaration
2855: * @param rewrite
2856: * the ast rewrite to use
2857: * @return the string representing the moved method body
2858: * @throws BadLocationException
2859: * if an offset into the document is invalid
2860: */
2861: protected String createMethodContent(final IDocument document,
2862: final MethodDeclaration declaration,
2863: final ASTRewrite rewrite) throws BadLocationException {
2864: Assert.isNotNull(document);
2865: Assert.isNotNull(declaration);
2866: Assert.isNotNull(rewrite);
2867: final IRegion range = new Region(
2868: declaration.getStartPosition(), declaration.getLength());
2869: final RangeMarker marker = new RangeMarker(range.getOffset(),
2870: range.getLength());
2871: final IJavaProject project = fMethod.getJavaProject();
2872: final TextEdit[] edits = rewrite.rewriteAST(document,
2873: project.getOptions(true)).removeChildren();
2874: for (int index = 0; index < edits.length; index++)
2875: marker.addChild(edits[index]);
2876: final MultiTextEdit result = new MultiTextEdit();
2877: result.addChild(marker);
2878: final TextEditProcessor processor = new TextEditProcessor(
2879: document, new MultiTextEdit(0, document.getLength()),
2880: TextEdit.UPDATE_REGIONS);
2881: processor.getRoot().addChild(result);
2882: processor.performEdits();
2883: final IRegion region = document.getLineInformation(document
2884: .getLineOfOffset(marker.getOffset()));
2885: return Strings.changeIndent(document.get(marker.getOffset(),
2886: marker.getLength()), Strings.computeIndentUnits(
2887: document.get(region.getOffset(), region.getLength()),
2888: project), project,
2889: "", TextUtilities.getDefaultLineDelimiter(document)); //$NON-NLS-1$
2890: }
2891:
2892: /**
2893: * Creates the necessary changes to create the delegate method with the
2894: * original method body.
2895: *
2896: * @param document
2897: * the buffer containing the source of the source compilation
2898: * unit
2899: * @param declaration
2900: * the method declaration to use as source
2901: * @param rewrite
2902: * the ast rewrite to use for the copy of the method body
2903: * @param rewrites
2904: * the compilation unit rewrites
2905: * @param adjustments
2906: * the map of elements to visibility adjustments
2907: * @param status
2908: * the refactoring status
2909: * @param monitor
2910: * the progress monitor to display progress
2911: * @throws CoreException
2912: * if an error occurs
2913: * @return <code>true</code> if a target node had to be inserted as first
2914: * argument, <code>false</code> otherwise
2915: */
2916: protected boolean createMethodCopy(final IDocument document,
2917: final MethodDeclaration declaration,
2918: final ASTRewrite rewrite, final Map rewrites,
2919: final Map adjustments, final RefactoringStatus status,
2920: final IProgressMonitor monitor) throws CoreException {
2921: Assert.isNotNull(document);
2922: Assert.isNotNull(declaration);
2923: Assert.isNotNull(rewrite);
2924: Assert.isNotNull(rewrites);
2925: Assert.isNotNull(adjustments);
2926: Assert.isNotNull(status);
2927: Assert.isNotNull(monitor);
2928: boolean target = false;
2929: final CompilationUnitRewrite rewriter = getCompilationUnitRewrite(
2930: rewrites, getTargetType().getCompilationUnit());
2931: try {
2932: rewrite.set(declaration, MethodDeclaration.NAME_PROPERTY,
2933: rewrite.getAST().newSimpleName(fMethodName), null);
2934: boolean same = false;
2935: final IMethodBinding binding = declaration.resolveBinding();
2936: if (binding != null) {
2937: final ITypeBinding declaring = binding
2938: .getDeclaringClass();
2939: if (declaring != null
2940: && Bindings.equals(declaring.getPackage(),
2941: fTarget.getType().getPackage()))
2942: same = true;
2943: final Modifier.ModifierKeyword keyword = same ? null
2944: : Modifier.ModifierKeyword.PUBLIC_KEYWORD;
2945: if (MemberVisibilityAdjustor.hasLowerVisibility(binding
2946: .getModifiers(), same ? Modifier.NONE
2947: : (keyword == null ? Modifier.NONE : keyword
2948: .toFlagValue()))
2949: && MemberVisibilityAdjustor
2950: .needsVisibilityAdjustments(fMethod,
2951: keyword, adjustments)) {
2952: final MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment adjustment = new MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment(
2953: fMethod,
2954: keyword,
2955: RefactoringStatus
2956: .createStatus(
2957: RefactoringStatus.WARNING,
2958: Messages
2959: .format(
2960: RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning,
2961: new String[] {
2962: MemberVisibilityAdjustor
2963: .getLabel(fMethod),
2964: MemberVisibilityAdjustor
2965: .getLabel(keyword) }),
2966: JavaStatusContext
2967: .create(fMethod),
2968: null,
2969: RefactoringStatusEntry.NO_CODE,
2970: null));
2971: ModifierRewrite.create(rewrite, declaration)
2972: .setVisibility(
2973: keyword == null ? Modifier.NONE
2974: : keyword.toFlagValue(),
2975: null);
2976: adjustment.setNeedsRewriting(false);
2977: adjustments.put(fMethod, adjustment);
2978: }
2979: }
2980: target = createMethodArguments(rewrites, rewrite,
2981: declaration, adjustments, status);
2982: createMethodTypeParameters(rewrite, declaration, status);
2983: createMethodComment(rewrite, declaration);
2984: createMethodBody(rewriter, rewrite, declaration);
2985: } finally {
2986: if (fMethod.getCompilationUnit().equals(
2987: getTargetType().getCompilationUnit()))
2988: rewriter.clearImportRewrites();
2989: }
2990: return target;
2991: }
2992:
2993: /**
2994: * Creates the necessary changes to replace the body of the method
2995: * declaration with an expression to invoke the delegate.
2996: *
2997: * @param declaration
2998: * the method declaration to replace its body
2999: * @param rewrites
3000: * the compilation unit rewrites
3001: * @param adjustments
3002: * the map of elements to visibility adjustments
3003: * @param status
3004: * the refactoring status
3005: * @param monitor
3006: * the progress monitor to display progress
3007: * @throws CoreException
3008: * if the change could not be generated
3009: * @return <code>true</code> if a target node had to be inserted as first
3010: * argument, <code>false</code> otherwise
3011: */
3012: protected boolean createMethodDelegation(
3013: final MethodDeclaration declaration, final Map rewrites,
3014: final Map adjustments, final RefactoringStatus status,
3015: final IProgressMonitor monitor) throws CoreException {
3016: Assert.isNotNull(declaration);
3017: Assert.isNotNull(monitor);
3018:
3019: final DelegateInstanceMethodCreator creator = new DelegateInstanceMethodCreator(
3020: adjustments, rewrites);
3021: creator.setSourceRewrite(fSourceRewrite);
3022: creator.setCopy(false);
3023: creator.setDeclareDeprecated(fDelegateDeprecation);
3024: creator.setDeclaration(declaration);
3025: creator.setNewElementName(fMethodName);
3026: creator.prepareDelegate();
3027: creator.createEdit();
3028:
3029: return creator.getNeededInsertion();
3030: }
3031:
3032: /**
3033: * Creates the necessary changes to inline the method invocations to the
3034: * original method.
3035: *
3036: * @param rewrites
3037: * the map of compilation units to compilation unit rewrites
3038: * @param declaration
3039: * the source method declaration
3040: * @param groups
3041: * the search result groups representing all references to the
3042: * moved method, including references in comments
3043: * @param adjustments
3044: * the map of elements to visibility adjustments
3045: * @param target
3046: * <code>true</code> if a target node must be inserted as first
3047: * argument, <code>false</code> otherwise
3048: * @param status
3049: * the refactoring status
3050: * @param monitor
3051: * the progress monitor to use
3052: * @return <code>true</code> if all method invocations to the original
3053: * method declaration could be inlined, <code>false</code>
3054: * otherwise
3055: */
3056: protected boolean createMethodDelegator(final Map rewrites,
3057: final MethodDeclaration declaration,
3058: final SearchResultGroup[] groups, final Map adjustments,
3059: final boolean target, final RefactoringStatus status,
3060: final IProgressMonitor monitor) {
3061: Assert.isNotNull(rewrites);
3062: Assert.isNotNull(declaration);
3063: Assert.isNotNull(groups);
3064: Assert.isNotNull(adjustments);
3065: Assert.isNotNull(status);
3066: Assert.isNotNull(monitor);
3067: try {
3068: monitor.beginTask("", groups.length); //$NON-NLS-1$
3069: monitor
3070: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
3071: try {
3072: boolean result = true;
3073: boolean found = false;
3074: final ITypeHierarchy hierarchy = fMethod
3075: .getDeclaringType().newTypeHierarchy(
3076: new SubProgressMonitor(monitor, 1));
3077: IType type = null;
3078: IMethod method = null;
3079: IType[] types = hierarchy.getAllSubtypes(fMethod
3080: .getDeclaringType());
3081: for (int index = 0; index < types.length && !found; index++) {
3082: type = types[index];
3083: method = JavaModelUtil.findMethod(fMethod
3084: .getElementName(), fMethod
3085: .getParameterTypes(), false, type);
3086: if (method != null)
3087: found = true;
3088: }
3089: types = hierarchy.getAllSupertypes(fMethod
3090: .getDeclaringType());
3091: for (int index = 0; index < types.length && !found; index++) {
3092: type = types[index];
3093: method = JavaModelUtil.findMethod(fMethod
3094: .getElementName(), fMethod
3095: .getParameterTypes(), false, type);
3096: if (method != null)
3097: found = true;
3098: }
3099: if (found) {
3100: status
3101: .merge(RefactoringStatus
3102: .createWarningStatus(
3103: Messages
3104: .format(
3105: RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_overridden,
3106: BindingLabelProvider
3107: .getBindingLabel(
3108: declaration
3109: .resolveBinding(),
3110: JavaElementLabels.ALL_FULLY_QUALIFIED)),
3111: JavaStatusContext
3112: .create(fMethod)));
3113: result = false;
3114: } else {
3115: monitor.worked(1);
3116: SearchMatch[] matches = null;
3117: IJavaElement element = null;
3118: ICompilationUnit unit = null;
3119: CompilationUnitRewrite rewrite = null;
3120: SearchResultGroup group = null;
3121: for (int index = 0; index < groups.length; index++) {
3122: group = groups[index];
3123: element = JavaCore.create(group.getResource());
3124: if (element instanceof ICompilationUnit) {
3125: matches = group.getSearchResults();
3126: unit = (ICompilationUnit) element;
3127: rewrite = getCompilationUnitRewrite(
3128: rewrites, unit);
3129: SearchMatch match = null;
3130: for (int offset = 0; offset < matches.length; offset++) {
3131: match = matches[offset];
3132: if (match.getAccuracy() == SearchMatch.A_INACCURATE) {
3133: status
3134: .merge(RefactoringStatus
3135: .createWarningStatus(
3136: Messages
3137: .format(
3138: RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_inaccurate,
3139: unit
3140: .getCorrespondingResource()
3141: .getName()),
3142: JavaStatusContext
3143: .create(
3144: unit,
3145: new SourceRange(
3146: match
3147: .getOffset(),
3148: match
3149: .getLength()))));
3150: result = false;
3151: } else if (!createInlinedMethodInvocation(
3152: rewrite, declaration, match,
3153: adjustments, target, status))
3154: result = false;
3155: }
3156: } else if (element != null) {
3157: status
3158: .merge(RefactoringStatus
3159: .createWarningStatus(Messages
3160: .format(
3161: RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_binary_project,
3162: element
3163: .getJavaProject()
3164: .getElementName())));
3165: result = false;
3166: } else {
3167: status
3168: .merge(RefactoringStatus
3169: .createWarningStatus(Messages
3170: .format(
3171: RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_binary_resource,
3172: group
3173: .getResource()
3174: .getName())));
3175: result = false;
3176: }
3177: }
3178: monitor.worked(1);
3179: }
3180: return result;
3181: } catch (CoreException exception) {
3182: status.merge(RefactoringStatus.create(exception
3183: .getStatus()));
3184: return false;
3185: }
3186: } finally {
3187: monitor.done();
3188: }
3189: }
3190:
3191: /**
3192: * Creates the necessary imports for the copied method in the target
3193: * compilation unit.
3194: *
3195: * @param rewrite
3196: * the target compilation unit rewrite
3197: * @param declaration
3198: * the source method declaration
3199: * @param monitor
3200: * the progress monitor to use
3201: * @param status
3202: * the refactoring status to use
3203: * @throws CoreException
3204: * if an error occurs
3205: */
3206: protected void createMethodImports(
3207: final CompilationUnitRewrite rewrite,
3208: final MethodDeclaration declaration,
3209: final IProgressMonitor monitor,
3210: final RefactoringStatus status) throws CoreException {
3211: Assert.isNotNull(rewrite);
3212: Assert.isNotNull(declaration);
3213: Assert.isNotNull(monitor);
3214: Assert.isNotNull(status);
3215: monitor.beginTask("", 1); //$NON-NLS-1$
3216: monitor
3217: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
3218: try {
3219: ImportRewriteUtil.addImports(rewrite, declaration,
3220: new HashMap(), new HashMap(), false);
3221: } finally {
3222: monitor.done();
3223: }
3224: }
3225:
3226: /**
3227: * Creates the necessary change to updated a comment reference represented
3228: * by a search match.
3229: *
3230: * @param rewrite
3231: * the current compilation unit rewrite
3232: * @param declaration
3233: * the source method declaration
3234: * @param match
3235: * the search match representing the method reference
3236: * @param targetNode
3237: * <code>true</code> if a target node had to be inserted as
3238: * first argument, <code>false</code> otherwise
3239: * @param status
3240: * the refactoring status
3241: */
3242: protected void createMethodJavadocReference(
3243: final CompilationUnitRewrite rewrite,
3244: final MethodDeclaration declaration,
3245: final SearchMatch match, final boolean targetNode,
3246: final RefactoringStatus status) {
3247: Assert.isNotNull(rewrite);
3248: Assert.isNotNull(declaration);
3249: Assert.isNotNull(match);
3250: Assert.isNotNull(status);
3251: final ASTNode node = ASTNodeSearchUtil.findNode(match, rewrite
3252: .getRoot());
3253: if (node instanceof MethodRef) {
3254: final AST ast = node.getAST();
3255: final MethodRef successor = ast.newMethodRef();
3256:
3257: rewrite.getASTRewrite().replace(node, successor, null);
3258: }
3259: }
3260:
3261: /**
3262: * Creates the necessary changes to update tag references to the original
3263: * method.
3264: *
3265: * @param rewrites
3266: * the map of compilation units to compilation unit rewrites
3267: * @param declaration
3268: * the source method declaration
3269: * @param groups
3270: * the search result groups representing all references to the
3271: * moved method, including references in comments
3272: * @param target
3273: * <code>true</code> if a target node must be inserted as first
3274: * argument, <code>false</code> otherwise
3275: * @param status
3276: * the refactoring status
3277: * @param monitor
3278: * the progress monitor to use
3279: */
3280: protected void createMethodJavadocReferences(final Map rewrites,
3281: final MethodDeclaration declaration,
3282: final SearchResultGroup[] groups, final boolean target,
3283: final RefactoringStatus status,
3284: final IProgressMonitor monitor) {
3285: Assert.isNotNull(rewrites);
3286: Assert.isNotNull(declaration);
3287: Assert.isNotNull(status);
3288: Assert.isNotNull(monitor);
3289: try {
3290: monitor.beginTask("", groups.length); //$NON-NLS-1$
3291: monitor
3292: .setTaskName(RefactoringCoreMessages.MoveInstanceMethodProcessor_creating);
3293: try {
3294: SearchMatch[] matches = null;
3295: IJavaElement element = null;
3296: ICompilationUnit unit = null;
3297: CompilationUnitRewrite rewrite = null;
3298: SearchResultGroup group = null;
3299: for (int index = 0; index < groups.length; index++) {
3300: group = groups[index];
3301: element = JavaCore.create(group.getResource());
3302: unit = group.getCompilationUnit();
3303: if (element instanceof ICompilationUnit) {
3304: matches = group.getSearchResults();
3305: unit = (ICompilationUnit) element;
3306: rewrite = getCompilationUnitRewrite(rewrites,
3307: unit);
3308: SearchMatch match = null;
3309: for (int offset = 0; offset < matches.length; offset++) {
3310: match = matches[offset];
3311: if (match.getAccuracy() == SearchMatch.A_INACCURATE) {
3312: status
3313: .merge(RefactoringStatus
3314: .createWarningStatus(
3315: Messages
3316: .format(
3317: RefactoringCoreMessages.MoveInstanceMethodProcessor_inline_inaccurate,
3318: unit
3319: .getCorrespondingResource()
3320: .getName()),
3321: JavaStatusContext
3322: .create(
3323: unit,
3324: new SourceRange(
3325: match
3326: .getOffset(),
3327: match
3328: .getLength()))));
3329: } else
3330: createMethodJavadocReference(rewrite,
3331: declaration, match, target,
3332: status);
3333: }
3334: } else if (element != null) {
3335: status
3336: .merge(RefactoringStatus
3337: .createWarningStatus(Messages
3338: .format(
3339: RefactoringCoreMessages.MoveInstanceMethodProcessor_javadoc_binary_project,
3340: element
3341: .getJavaProject()
3342: .getElementName())));
3343: } else {
3344: status
3345: .merge(RefactoringStatus
3346: .createWarningStatus(Messages
3347: .format(
3348: RefactoringCoreMessages.MoveInstanceMethodProcessor_javadoc_binary_resource,
3349: group
3350: .getResource()
3351: .getName())));
3352: }
3353: monitor.worked(1);
3354: }
3355: } catch (CoreException exception) {
3356: status.merge(RefactoringStatus.create(exception
3357: .getStatus()));
3358: }
3359: } finally {
3360: monitor.done();
3361: }
3362: }
3363:
3364: /**
3365: * Creates a comment method reference to the moved method
3366: *
3367: * @param declaration
3368: * the method declaration of the original method
3369: * @param ast
3370: * the ast to create the method reference for
3371: * @return the created link tag to reference the method
3372: * @throws JavaModelException
3373: * if an error occurs
3374: */
3375: protected ASTNode createMethodReference(
3376: final MethodDeclaration declaration, final AST ast)
3377: throws JavaModelException {
3378: Assert.isNotNull(ast);
3379: Assert.isNotNull(declaration);
3380: final MethodRef reference = ast.newMethodRef();
3381: reference.setName(ast.newSimpleName(fMethodName));
3382: reference.setQualifier(ASTNodeFactory.newName(ast,
3383: JavaModelUtil.getFullyQualifiedName(fTargetType)));
3384: createArgumentList(declaration, reference.parameters(),
3385: new IArgumentFactory() {
3386:
3387: public final ASTNode getArgumentNode(
3388: final IVariableBinding binding,
3389: final boolean last) {
3390: Assert.isNotNull(binding);
3391: final MethodRefParameter parameter = ast
3392: .newMethodRefParameter();
3393: parameter.setType(ASTNodeFactory.newType(ast,
3394: binding.getType().getName()));
3395: return parameter;
3396: }
3397:
3398: public final ASTNode getTargetNode() {
3399: final MethodRefParameter parameter = ast
3400: .newMethodRefParameter();
3401: final IMethodBinding method = declaration
3402: .resolveBinding();
3403: if (method != null) {
3404: final ITypeBinding declaring = method
3405: .getDeclaringClass();
3406: if (declaring != null)
3407: parameter
3408: .setType(ASTNodeFactory
3409: .newType(
3410: ast,
3411: Bindings
3412: .getFullyQualifiedName(declaring)));
3413: }
3414: return parameter;
3415: }
3416: });
3417: return reference;
3418: }
3419:
3420: /**
3421: * @param document
3422: * the buffer containing the source of the source compilation
3423: * unit
3424: * @param declaration
3425: * the method declaration to use as source
3426: * @param rewrite
3427: * the ast rewrite to use for the copy of the method body
3428: * @param rewrites
3429: * the compilation unit rewrites
3430: * @throws JavaModelException
3431: * if the insertion point cannot be found
3432: */
3433: protected void createMethodSignature(final IDocument document,
3434: final MethodDeclaration declaration,
3435: final ASTRewrite rewrite, final Map rewrites)
3436: throws JavaModelException {
3437: Assert.isNotNull(document);
3438: Assert.isNotNull(declaration);
3439: Assert.isNotNull(rewrite);
3440: Assert.isNotNull(rewrites);
3441: try {
3442: final CompilationUnitRewrite rewriter = getCompilationUnitRewrite(
3443: rewrites, getTargetType().getCompilationUnit());
3444: final MethodDeclaration stub = (MethodDeclaration) rewriter
3445: .getASTRewrite().createStringPlaceholder(
3446: createMethodContent(document, declaration,
3447: rewrite),
3448: ASTNode.METHOD_DECLARATION);
3449: final AbstractTypeDeclaration type = ASTNodeSearchUtil
3450: .getAbstractTypeDeclarationNode(getTargetType(),
3451: rewriter.getRoot());
3452: rewriter
3453: .getASTRewrite()
3454: .getListRewrite(type,
3455: type.getBodyDeclarationsProperty())
3456: .insertAt(
3457: stub,
3458: ASTNodes.getInsertionIndex(stub, type
3459: .bodyDeclarations()),
3460: rewriter
3461: .createGroupDescription(RefactoringCoreMessages.MoveInstanceMethodProcessor_add_moved_method));
3462: } catch (BadLocationException exception) {
3463: JavaPlugin.log(exception);
3464: }
3465: }
3466:
3467: /**
3468: * Creates the necessary changes to remove method type parameters if they
3469: * match with enclosing type parameters.
3470: *
3471: * @param rewrite
3472: * the ast rewrite to use
3473: * @param declaration
3474: * the method declaration to remove type parameters
3475: * @param status
3476: * the refactoring status
3477: */
3478: protected void createMethodTypeParameters(final ASTRewrite rewrite,
3479: final MethodDeclaration declaration,
3480: final RefactoringStatus status) {
3481: ITypeBinding binding = fTarget.getType();
3482: if (binding != null && binding.isParameterizedType()) {
3483: final IMethodBinding method = declaration.resolveBinding();
3484: if (method != null) {
3485: final ITypeBinding[] parameters = method
3486: .getTypeParameters();
3487: if (parameters.length > 0) {
3488: final ListRewrite rewriter = rewrite
3489: .getListRewrite(
3490: declaration,
3491: MethodDeclaration.TYPE_PARAMETERS_PROPERTY);
3492: boolean foundStatic = false;
3493: while (binding != null && !foundStatic) {
3494: if (Flags.isStatic(binding.getModifiers()))
3495: foundStatic = true;
3496: final ITypeBinding[] bindings = binding
3497: .getTypeArguments();
3498: for (int index = 0; index < bindings.length; index++) {
3499: for (int offset = 0; offset < parameters.length; offset++) {
3500: if (parameters[offset].getName()
3501: .equals(
3502: bindings[index]
3503: .getName())) {
3504: rewriter.remove((ASTNode) rewriter
3505: .getOriginalList().get(
3506: offset), null);
3507: status
3508: .addWarning(
3509: Messages
3510: .format(
3511: RefactoringCoreMessages.MoveInstanceMethodProcessor_present_type_parameter_warning,
3512: new Object[] {
3513: parameters[offset]
3514: .getName(),
3515: BindingLabelProvider
3516: .getBindingLabel(
3517: binding,
3518: JavaElementLabels.ALL_FULLY_QUALIFIED) }),
3519: JavaStatusContext
3520: .create(fMethod));
3521: }
3522: }
3523: }
3524: binding = binding.getDeclaringClass();
3525: }
3526: }
3527: }
3528: }
3529: }
3530:
3531: /**
3532: * Creates the expression to access the new target.
3533: *
3534: * @param declaration
3535: * the method declaration where to access the target
3536: * @return the corresponding expression
3537: */
3538: protected Expression createSimpleTargetAccessExpression(
3539: final MethodDeclaration declaration) {
3540: Assert.isNotNull(declaration);
3541: Expression expression = null;
3542: final AST ast = declaration.getAST();
3543: final ITypeBinding type = fTarget.getDeclaringClass();
3544: if (type != null) {
3545: boolean shadows = false;
3546: final IVariableBinding[] bindings = getArgumentBindings(declaration);
3547: IVariableBinding variable = null;
3548: for (int index = 0; index < bindings.length; index++) {
3549: variable = bindings[index];
3550: if (fMethod.getDeclaringType().getField(
3551: variable.getName()).exists()) {
3552: shadows = true;
3553: break;
3554: }
3555: }
3556: if (fSettings.useKeywordThis || shadows) {
3557: final FieldAccess access = ast.newFieldAccess();
3558: access.setName(ast.newSimpleName(fTarget.getName()));
3559: access.setExpression(ast.newThisExpression());
3560: expression = access;
3561: } else
3562: expression = ast.newSimpleName(fTarget.getName());
3563: } else
3564: expression = ast.newSimpleName(fTarget.getName());
3565: return expression;
3566: }
3567:
3568: /**
3569: * Returns the candidate targets for the method to move.
3570: *
3571: * @return the candidate targets as variable bindings of fields and
3572: * parameters
3573: */
3574: public final IVariableBinding[] getCandidateTargets() {
3575: Assert.isNotNull(fCandidateTargets);
3576: return fCandidateTargets;
3577: }
3578:
3579: /**
3580: * {@inheritDoc}
3581: */
3582: public String getComment() {
3583: return fComment;
3584: }
3585:
3586: /**
3587: * Returns a compilation unit rewrite for the specified compilation unit.
3588: *
3589: * @param rewrites
3590: * the compilation unit rewrite map
3591: * @param unit
3592: * the compilation unit
3593: * @return the corresponding compilation unit rewrite
3594: */
3595: protected CompilationUnitRewrite getCompilationUnitRewrite(
3596: final Map rewrites, final ICompilationUnit unit) {
3597: Assert.isNotNull(rewrites);
3598: Assert.isNotNull(unit);
3599: CompilationUnitRewrite rewrite = (CompilationUnitRewrite) rewrites
3600: .get(unit);
3601: if (rewrite == null) {
3602: rewrite = new CompilationUnitRewrite(unit);
3603: rewrites.put(unit, rewrite);
3604: }
3605: return rewrite;
3606: }
3607:
3608: /**
3609: * {@inheritDoc}
3610: */
3611: public final boolean getDelegateUpdating() {
3612: return fDelegatingUpdating;
3613: }
3614:
3615: /**
3616: * {@inheritDoc}
3617: */
3618: public String getDelegateUpdatingTitle(boolean plural) {
3619: if (plural)
3620: return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_plural;
3621: else
3622: return RefactoringCoreMessages.DelegateMethodCreator_keep_original_moved_singular;
3623: }
3624:
3625: /**
3626: * {@inheritDoc}
3627: */
3628: public final boolean getDeprecateDelegates() {
3629: return fDelegateDeprecation;
3630: }
3631:
3632: /**
3633: * {@inheritDoc}
3634: */
3635: public final Object[] getElements() {
3636: return new Object[] { fMethod };
3637: }
3638:
3639: /**
3640: * {@inheritDoc}
3641: */
3642: public final String getIdentifier() {
3643: return IDENTIFIER;
3644: }
3645:
3646: /**
3647: * Returns the method to be moved.
3648: *
3649: * @return the method to be moved
3650: */
3651: public final IMethod getMethod() {
3652: return fMethod;
3653: }
3654:
3655: /**
3656: * Returns the new method name.
3657: *
3658: * @return the name of the new method
3659: */
3660: public final String getMethodName() {
3661: return fMethodName;
3662: }
3663:
3664: /**
3665: * Returns the possible targets for the method to move.
3666: *
3667: * @return the possible targets as variable bindings of read-only fields and
3668: * parameters
3669: */
3670: public final IVariableBinding[] getPossibleTargets() {
3671: Assert.isNotNull(fPossibleTargets);
3672: return fPossibleTargets;
3673: }
3674:
3675: /*
3676: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
3677: */
3678: public final String getProcessorName() {
3679: return RefactoringCoreMessages.MoveInstanceMethodProcessor_name;
3680: }
3681:
3682: /**
3683: * Returns the index of the chosen target.
3684: *
3685: * @return the target index
3686: */
3687: protected final int getTargetIndex() {
3688: final IVariableBinding[] targets = getPossibleTargets();
3689: int result = -1;
3690: for (int index = 0; index < targets.length; index++) {
3691: if (Bindings.equals(fTarget, targets[index])) {
3692: result = index;
3693: break;
3694: }
3695: }
3696: return result;
3697: }
3698:
3699: /**
3700: * Returns the new target name.
3701: *
3702: * @return the name of the new target
3703: */
3704: public final String getTargetName() {
3705: return fTargetName;
3706: }
3707:
3708: /**
3709: * Returns the type of the new target.
3710: *
3711: * @return the type of the new target
3712: * @throws JavaModelException
3713: * if the type does not exist
3714: */
3715: protected IType getTargetType() throws JavaModelException {
3716: Assert.isNotNull(fTarget);
3717: if (fTargetType == null) {
3718: final ITypeBinding binding = fTarget.getType();
3719: if (binding != null)
3720: fTargetType = (IType) binding.getJavaElement();
3721: else
3722: throw new JavaModelException(
3723: new CoreException(
3724: new Status(
3725: IStatus.ERROR,
3726: JavaPlugin.getPluginId(),
3727: 0,
3728: RefactoringCoreMessages.MoveInstanceMethodProcessor_cannot_be_moved,
3729: null)));
3730: }
3731: return fTargetType;
3732: }
3733:
3734: /**
3735: * Initializes the refactoring with the given input.
3736: *
3737: * @param method
3738: * the method to move
3739: */
3740: protected void initialize(final IMethod method) {
3741: Assert.isNotNull(method);
3742: fSourceRewrite = new CompilationUnitRewrite(fMethod
3743: .getCompilationUnit());
3744: fMethodName = method.getElementName();
3745: fTargetName = suggestTargetName();
3746: if (fSettings == null)
3747: fSettings = JavaPreferencesSettings
3748: .getCodeGenerationSettings(fMethod.getJavaProject());
3749: }
3750:
3751: /**
3752: * {@inheritDoc}
3753: */
3754: public RefactoringStatus initialize(
3755: final RefactoringArguments arguments) {
3756: if (arguments instanceof JavaRefactoringArguments) {
3757: final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
3758: final String handle = extended
3759: .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
3760: if (handle != null) {
3761: final IJavaElement element = JavaRefactoringDescriptorUtil
3762: .handleToElement(extended.getProject(), handle,
3763: false);
3764: if (element == null
3765: || !element.exists()
3766: || element.getElementType() != IJavaElement.METHOD)
3767: return ScriptableRefactoring
3768: .createInputFatalStatus(element,
3769: getRefactoring().getName(),
3770: IJavaRefactorings.MOVE_METHOD);
3771: else {
3772: fMethod = (IMethod) element;
3773: initialize(fMethod);
3774: }
3775: } else
3776: return RefactoringStatus
3777: .createFatalErrorStatus(Messages
3778: .format(
3779: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3780: JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
3781: final String name = extended
3782: .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
3783: if (name != null) {
3784: final RefactoringStatus status = setMethodName(name);
3785: if (status.hasError())
3786: return status;
3787: } else
3788: return RefactoringStatus
3789: .createFatalErrorStatus(Messages
3790: .format(
3791: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3792: JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
3793: final String deprecate = extended
3794: .getAttribute(ATTRIBUTE_DEPRECATE);
3795: if (deprecate != null) {
3796: fDelegateDeprecation = Boolean.valueOf(deprecate)
3797: .booleanValue();
3798: } else
3799: return RefactoringStatus
3800: .createFatalErrorStatus(Messages
3801: .format(
3802: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3803: ATTRIBUTE_DEPRECATE));
3804: final String remove = extended
3805: .getAttribute(ATTRIBUTE_REMOVE);
3806: if (remove != null) {
3807: fRemove = Boolean.valueOf(remove).booleanValue();
3808: } else
3809: return RefactoringStatus
3810: .createFatalErrorStatus(Messages
3811: .format(
3812: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3813: ATTRIBUTE_REMOVE));
3814: final String inline = extended
3815: .getAttribute(ATTRIBUTE_INLINE);
3816: if (inline != null) {
3817: fInline = Boolean.valueOf(inline).booleanValue();
3818: } else
3819: return RefactoringStatus
3820: .createFatalErrorStatus(Messages
3821: .format(
3822: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3823: ATTRIBUTE_INLINE));
3824: final String getter = extended
3825: .getAttribute(ATTRIBUTE_USE_GETTER);
3826: if (getter != null)
3827: fUseGetters = Boolean.valueOf(getter).booleanValue();
3828: else
3829: return RefactoringStatus
3830: .createFatalErrorStatus(Messages
3831: .format(
3832: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3833: ATTRIBUTE_USE_GETTER));
3834: final String setter = extended
3835: .getAttribute(ATTRIBUTE_USE_SETTER);
3836: if (setter != null)
3837: fUseSetters = Boolean.valueOf(setter).booleanValue();
3838: else
3839: return RefactoringStatus
3840: .createFatalErrorStatus(Messages
3841: .format(
3842: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3843: ATTRIBUTE_USE_SETTER));
3844: final String target = extended
3845: .getAttribute(ATTRIBUTE_TARGET_NAME);
3846: if (target != null) {
3847: final RefactoringStatus status = setTargetName(target);
3848: if (status.hasError())
3849: return status;
3850: } else
3851: return RefactoringStatus
3852: .createFatalErrorStatus(Messages
3853: .format(
3854: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3855: ATTRIBUTE_TARGET_NAME));
3856: final String value = extended
3857: .getAttribute(ATTRIBUTE_TARGET_INDEX);
3858: if (value != null) {
3859: try {
3860: final int index = Integer.valueOf(value).intValue();
3861: if (index >= 0) {
3862: final MethodDeclaration declaration = ASTNodeSearchUtil
3863: .getMethodDeclarationNode(fMethod,
3864: fSourceRewrite.getRoot());
3865: if (declaration != null) {
3866: final IVariableBinding[] bindings = computeTargetCategories(declaration);
3867: if (bindings != null
3868: && index < bindings.length)
3869: setTarget(bindings[index]);
3870: }
3871: }
3872: } catch (NumberFormatException exception) {
3873: return RefactoringStatus
3874: .createFatalErrorStatus(Messages
3875: .format(
3876: RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
3877: new String[] { value,
3878: ATTRIBUTE_TARGET_INDEX }));
3879: } catch (JavaModelException exception) {
3880: return RefactoringStatus
3881: .createFatalErrorStatus(Messages
3882: .format(
3883: RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
3884: new String[] { value,
3885: ATTRIBUTE_TARGET_INDEX }));
3886: }
3887: } else
3888: return RefactoringStatus
3889: .createFatalErrorStatus(Messages
3890: .format(
3891: RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
3892: ATTRIBUTE_TARGET_INDEX));
3893: } else
3894: return RefactoringStatus
3895: .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
3896: return new RefactoringStatus();
3897: }
3898:
3899: /*
3900: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#isApplicable()
3901: */
3902: public final boolean isApplicable() throws CoreException {
3903: return fMethod.exists() && !fMethod.isConstructor()
3904: && !fMethod.isBinary() && !fMethod.isReadOnly()
3905: && fMethod.getCompilationUnit() != null
3906: && !JdtFlags.isStatic(fMethod);
3907: }
3908:
3909: /**
3910: * Is the specified name a target access?
3911: *
3912: * @param name
3913: * the name to check
3914: * @return <code>true</code> if this name is a target access,
3915: * <code>false</code> otherwise
3916: */
3917: protected boolean isTargetAccess(final Name name) {
3918: Assert.isNotNull(name);
3919: final IBinding binding = name.resolveBinding();
3920: if (Bindings.equals(fTarget, binding))
3921: return true;
3922: if (name.getParent() instanceof FieldAccess) {
3923: final FieldAccess access = (FieldAccess) name.getParent();
3924: final Expression expression = access.getExpression();
3925: if (expression instanceof Name)
3926: return isTargetAccess((Name) expression);
3927: } else if (name instanceof QualifiedName) {
3928: final QualifiedName qualified = (QualifiedName) name;
3929: if (qualified.getQualifier() != null)
3930: return isTargetAccess(qualified.getQualifier());
3931: }
3932: return false;
3933: }
3934:
3935: /*
3936: * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#loadParticipants(org.eclipse.ltk.core.refactoring.RefactoringStatus,
3937: * org.eclipse.ltk.core.refactoring.participants.SharableParticipants)
3938: */
3939: public final RefactoringParticipant[] loadParticipants(
3940: final RefactoringStatus status,
3941: final SharableParticipants participants)
3942: throws CoreException {
3943: return new RefactoringParticipant[0];
3944: }
3945:
3946: /**
3947: * Does the moved method need a target node?
3948: *
3949: * @return <code>true</code> if it needs a target node, <code>false</code>
3950: * otherwise
3951: */
3952: public final boolean needsTargetNode() {
3953: return fTargetNode;
3954: }
3955:
3956: /**
3957: * {@inheritDoc}
3958: */
3959: public void setComment(final String comment) {
3960: fComment = comment;
3961: }
3962:
3963: /**
3964: * {@inheritDoc}
3965: */
3966: public final void setDelegateUpdating(final boolean updating) {
3967: fDelegatingUpdating = updating;
3968: setInlineDelegator(!updating);
3969: setRemoveDelegator(!updating);
3970: }
3971:
3972: /**
3973: * {@inheritDoc}
3974: */
3975: public final void setDeprecateDelegates(final boolean deprecate) {
3976: fDelegateDeprecation = deprecate;
3977: }
3978:
3979: /**
3980: * Determines whether the delegator has to be inlined.
3981: *
3982: * @param inline
3983: * <code>true</code> to inline the delegator,
3984: * <code>false</code> otherwise
3985: */
3986: public final void setInlineDelegator(final boolean inline) {
3987: fInline = inline;
3988: }
3989:
3990: /**
3991: * Sets the new method name.
3992: *
3993: * @param name
3994: * the name to set
3995: * @return the status of the operation
3996: */
3997: public final RefactoringStatus setMethodName(final String name) {
3998: Assert.isNotNull(name);
3999: RefactoringStatus status = Checks.checkMethodName(name,
4000: fTargetType);
4001: if (status.hasFatalError())
4002: return status;
4003: fMethodName = name;
4004: return status;
4005: }
4006:
4007: /**
4008: * Determines whether the delegator has to be removed after inlining. Note
4009: * that the option to inline the delegator has to be enabled if this method
4010: * is called with the argument <code>true</code>.
4011: *
4012: * @param remove
4013: * <code>true</code> if it should be removed,
4014: * <code>false</code> otherwise
4015: */
4016: public final void setRemoveDelegator(final boolean remove) {
4017: Assert.isTrue(!remove || fInline);
4018: fRemove = remove;
4019: }
4020:
4021: /**
4022: * Sets the new target.
4023: *
4024: * @param target
4025: * the target to set
4026: */
4027: public final void setTarget(final IVariableBinding target) {
4028: Assert.isNotNull(target);
4029: fTarget = target;
4030: fTargetType = null;
4031: try {
4032: final MethodDeclaration declaration = ASTNodeSearchUtil
4033: .getMethodDeclarationNode(fMethod, fSourceRewrite
4034: .getRoot());
4035: if (declaration != null) {
4036: final AstNodeFinder finder = new ThisReferenceFinder();
4037: declaration.accept(finder);
4038: fTargetNode = !finder.getResult().isEmpty();
4039: return;
4040: }
4041: } catch (JavaModelException exception) {
4042: JavaPlugin.log(exception);
4043: }
4044: fTargetNode = true;
4045: }
4046:
4047: /**
4048: * Sets the new target name.
4049: *
4050: * @param name
4051: * the name to set
4052: * @return the status of the operation
4053: */
4054: public final RefactoringStatus setTargetName(final String name) {
4055: Assert.isNotNull(name);
4056: final RefactoringStatus status = Checks.checkTempName(name,
4057: fMethod);
4058: if (status.hasFatalError())
4059: return status;
4060: fTargetName = name;
4061: return status;
4062: }
4063:
4064: /**
4065: * Determines whether getter methods should be used to resolve visibility
4066: * issues.
4067: *
4068: * @param use
4069: * <code>true</code> if getter methods should be used,
4070: * <code>false</code> otherwise
4071: */
4072: public final void setUseGetters(final boolean use) {
4073: fUseGetters = use;
4074: }
4075:
4076: /**
4077: * Determines whether setter methods should be used to resolve visibility
4078: * issues.
4079: *
4080: * @param use
4081: * <code>true</code> if setter methods should be used,
4082: * <code>false</code> otherwise
4083: */
4084: public final void setUseSetters(final boolean use) {
4085: fUseSetters = use;
4086: }
4087:
4088: /**
4089: * Should getter methods be used to resolve visibility issues?
4090: *
4091: * @return <code>true</code> if getter methods should be used,
4092: * <code>false</code> otherwise
4093: */
4094: public final boolean shouldUseGetters() {
4095: return fUseGetters;
4096: }
4097:
4098: /**
4099: * Should setter methods be used to resolve visibility issues?
4100: *
4101: * @return <code>true</code> if setter methods should be used,
4102: * <code>false</code> otherwise
4103: */
4104: public final boolean shouldUseSetters() {
4105: return fUseSetters;
4106: }
4107:
4108: /**
4109: * Returns a best guess for the name of the new target.
4110: *
4111: * @return a best guess for the name
4112: */
4113: protected String suggestTargetName() {
4114: try {
4115: final String[] candidates = StubUtility
4116: .getArgumentNameSuggestions(fMethod
4117: .getDeclaringType(),
4118: computeReservedIdentifiers());
4119: if (candidates.length > 0) {
4120: if (candidates[0].indexOf('$') < 0)
4121: return candidates[0];
4122: }
4123: } catch (JavaModelException exception) {
4124: JavaPlugin.log(exception);
4125: }
4126: return "arg"; //$NON-NLS-1$
4127: }
4128: }
|