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.ui.text.correction;
0011:
0012: import java.util.Collection;
0013: import java.util.Hashtable;
0014: import java.util.List;
0015: import java.util.Map;
0016:
0017: import org.eclipse.text.edits.MultiTextEdit;
0018: import org.eclipse.text.edits.ReplaceEdit;
0019: import org.eclipse.text.edits.TextEdit;
0020:
0021: import org.eclipse.core.runtime.Assert;
0022: import org.eclipse.core.runtime.CoreException;
0023: import org.eclipse.core.runtime.IStatus;
0024: import org.eclipse.core.runtime.Status;
0025:
0026: import org.eclipse.swt.graphics.Image;
0027:
0028: import org.eclipse.jface.text.BadLocationException;
0029: import org.eclipse.jface.text.IDocument;
0030: import org.eclipse.jface.text.link.LinkedModeModel;
0031: import org.eclipse.jface.text.link.LinkedPosition;
0032:
0033: import org.eclipse.jdt.core.ICompilationUnit;
0034: import org.eclipse.jdt.core.JavaModelException;
0035: import org.eclipse.jdt.core.compiler.IProblem;
0036: import org.eclipse.jdt.core.dom.AST;
0037: import org.eclipse.jdt.core.dom.ASTNode;
0038: import org.eclipse.jdt.core.dom.Annotation;
0039: import org.eclipse.jdt.core.dom.Block;
0040: import org.eclipse.jdt.core.dom.ClassInstanceCreation;
0041: import org.eclipse.jdt.core.dom.CompilationUnit;
0042: import org.eclipse.jdt.core.dom.Expression;
0043: import org.eclipse.jdt.core.dom.FieldAccess;
0044: import org.eclipse.jdt.core.dom.IBinding;
0045: import org.eclipse.jdt.core.dom.IMethodBinding;
0046: import org.eclipse.jdt.core.dom.ITypeBinding;
0047: import org.eclipse.jdt.core.dom.IVariableBinding;
0048: import org.eclipse.jdt.core.dom.Javadoc;
0049: import org.eclipse.jdt.core.dom.MethodDeclaration;
0050: import org.eclipse.jdt.core.dom.MethodInvocation;
0051: import org.eclipse.jdt.core.dom.Modifier;
0052: import org.eclipse.jdt.core.dom.QualifiedName;
0053: import org.eclipse.jdt.core.dom.ReturnStatement;
0054: import org.eclipse.jdt.core.dom.SimpleName;
0055: import org.eclipse.jdt.core.dom.SimpleType;
0056: import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
0057: import org.eclipse.jdt.core.dom.SuperFieldAccess;
0058: import org.eclipse.jdt.core.dom.SuperMethodInvocation;
0059: import org.eclipse.jdt.core.dom.TagElement;
0060: import org.eclipse.jdt.core.dom.Type;
0061: import org.eclipse.jdt.core.dom.TypeDeclaration;
0062: import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
0063: import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
0064: import org.eclipse.jdt.core.formatter.IndentManipulation;
0065:
0066: import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0067: import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0068: import org.eclipse.jdt.internal.corext.dom.Bindings;
0069: import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
0070: import org.eclipse.jdt.internal.corext.fix.IProposableFix;
0071: import org.eclipse.jdt.internal.corext.fix.Java50Fix;
0072: import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
0073: import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup;
0074: import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFix;
0075: import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
0076: import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFix.MakeTypeAbstractOperation;
0077: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0078: import org.eclipse.jdt.internal.corext.util.JdtFlags;
0079: import org.eclipse.jdt.internal.corext.util.Messages;
0080:
0081: import org.eclipse.jdt.ui.JavaUI;
0082: import org.eclipse.jdt.ui.text.java.IInvocationContext;
0083: import org.eclipse.jdt.ui.text.java.IProblemLocation;
0084:
0085: import org.eclipse.jdt.internal.ui.JavaPluginImages;
0086: import org.eclipse.jdt.internal.ui.fix.Java50CleanUp;
0087: import org.eclipse.jdt.internal.ui.text.correction.proposals.ASTRewriteCorrectionProposal;
0088: import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;
0089: import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
0090: import org.eclipse.jdt.internal.ui.text.correction.proposals.ModifierChangeCorrectionProposal;
0091:
0092: /**
0093: */
0094: public class ModifierCorrectionSubProcessor {
0095:
0096: public static final int TO_STATIC = 1;
0097: public static final int TO_VISIBLE = 2;
0098: public static final int TO_NON_PRIVATE = 3;
0099: public static final int TO_NON_STATIC = 4;
0100: public static final int TO_NON_FINAL = 5;
0101:
0102: public static void addNonAccessibleReferenceProposal(
0103: IInvocationContext context, IProblemLocation problem,
0104: Collection proposals, int kind, int relevance)
0105: throws CoreException {
0106: ICompilationUnit cu = context.getCompilationUnit();
0107:
0108: ASTNode selectedNode = problem.getCoveringNode(context
0109: .getASTRoot());
0110: if (selectedNode == null) {
0111: return;
0112: }
0113:
0114: IBinding binding = null;
0115: switch (selectedNode.getNodeType()) {
0116: case ASTNode.SIMPLE_NAME:
0117: binding = ((SimpleName) selectedNode).resolveBinding();
0118: break;
0119: case ASTNode.QUALIFIED_NAME:
0120: binding = ((QualifiedName) selectedNode).resolveBinding();
0121: break;
0122: case ASTNode.SIMPLE_TYPE:
0123: binding = ((SimpleType) selectedNode).resolveBinding();
0124: break;
0125: case ASTNode.METHOD_INVOCATION:
0126: binding = ((MethodInvocation) selectedNode).getName()
0127: .resolveBinding();
0128: break;
0129: case ASTNode.SUPER_METHOD_INVOCATION:
0130: binding = ((SuperMethodInvocation) selectedNode).getName()
0131: .resolveBinding();
0132: break;
0133: case ASTNode.FIELD_ACCESS:
0134: binding = ((FieldAccess) selectedNode).getName()
0135: .resolveBinding();
0136: break;
0137: case ASTNode.SUPER_FIELD_ACCESS:
0138: binding = ((SuperFieldAccess) selectedNode).getName()
0139: .resolveBinding();
0140: break;
0141: case ASTNode.CLASS_INSTANCE_CREATION:
0142: binding = ((ClassInstanceCreation) selectedNode)
0143: .resolveConstructorBinding();
0144: break;
0145: case ASTNode.SUPER_CONSTRUCTOR_INVOCATION:
0146: binding = ((SuperConstructorInvocation) selectedNode)
0147: .resolveConstructorBinding();
0148: break;
0149: default:
0150: return;
0151: }
0152: ITypeBinding typeBinding = null;
0153: String name;
0154: IBinding bindingDecl;
0155: boolean isLocalVar = false;
0156: if (binding instanceof IMethodBinding) {
0157: IMethodBinding methodDecl = (IMethodBinding) binding;
0158: bindingDecl = methodDecl.getMethodDeclaration();
0159: typeBinding = methodDecl.getDeclaringClass();
0160: name = methodDecl.getName() + "()"; //$NON-NLS-1$
0161: } else if (binding instanceof IVariableBinding) {
0162: IVariableBinding varDecl = (IVariableBinding) binding;
0163: typeBinding = varDecl.getDeclaringClass();
0164: name = binding.getName();
0165: isLocalVar = !varDecl.isField();
0166: bindingDecl = varDecl.getVariableDeclaration();
0167: } else if (binding instanceof ITypeBinding) {
0168: typeBinding = (ITypeBinding) binding;
0169: bindingDecl = typeBinding.getTypeDeclaration();
0170: name = binding.getName();
0171: } else {
0172: return;
0173: }
0174: if (typeBinding != null && typeBinding.isFromSource()
0175: || isLocalVar) {
0176: int includedModifiers = 0;
0177: int excludedModifiers = 0;
0178: String label;
0179: switch (kind) {
0180: case TO_VISIBLE:
0181: excludedModifiers = Modifier.PRIVATE
0182: | Modifier.PROTECTED | Modifier.PUBLIC;
0183: includedModifiers = getNeededVisibility(selectedNode,
0184: typeBinding);
0185: label = Messages
0186: .format(
0187: CorrectionMessages.ModifierCorrectionSubProcessor_changevisibility_description,
0188: new String[] {
0189: name,
0190: getVisibilityString(includedModifiers) });
0191: break;
0192: case TO_STATIC:
0193: label = Messages
0194: .format(
0195: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertostatic_description,
0196: name);
0197: includedModifiers = Modifier.STATIC;
0198: break;
0199: case TO_NON_STATIC:
0200: label = Messages
0201: .format(
0202: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertononstatic_description,
0203: name);
0204: excludedModifiers = Modifier.STATIC;
0205: break;
0206: case TO_NON_PRIVATE:
0207: label = Messages
0208: .format(
0209: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertodefault_description,
0210: name);
0211: excludedModifiers = Modifier.PRIVATE;
0212: break;
0213: case TO_NON_FINAL:
0214: label = Messages
0215: .format(
0216: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertononfinal_description,
0217: name);
0218: excludedModifiers = Modifier.FINAL;
0219: break;
0220: default:
0221: throw new IllegalArgumentException("not supported"); //$NON-NLS-1$
0222: }
0223: ICompilationUnit targetCU = isLocalVar ? cu : ASTResolving
0224: .findCompilationUnitForBinding(cu, context
0225: .getASTRoot(), typeBinding
0226: .getTypeDeclaration());
0227: if (targetCU != null) {
0228: Image image = JavaPluginImages
0229: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0230: proposals.add(new ModifierChangeCorrectionProposal(
0231: label, targetCU, bindingDecl, selectedNode,
0232: includedModifiers, excludedModifiers,
0233: relevance, image));
0234: }
0235: }
0236: if (kind == TO_VISIBLE
0237: && bindingDecl.getKind() == IBinding.VARIABLE) {
0238: UnresolvedElementsSubProcessor.getVariableProposals(
0239: context, problem, (IVariableBinding) bindingDecl,
0240: proposals);
0241: }
0242: }
0243:
0244: public static void addChangeOverriddenModfierProposal(
0245: IInvocationContext context, IProblemLocation problem,
0246: Collection proposals, int kind) throws JavaModelException {
0247: ICompilationUnit cu = context.getCompilationUnit();
0248:
0249: ASTNode selectedNode = problem.getCoveringNode(context
0250: .getASTRoot());
0251: if (!(selectedNode instanceof MethodDeclaration)) {
0252: return;
0253: }
0254:
0255: IMethodBinding method = ((MethodDeclaration) selectedNode)
0256: .resolveBinding();
0257: ITypeBinding curr = method.getDeclaringClass();
0258:
0259: if (kind == TO_VISIBLE
0260: && problem.getProblemId() != IProblem.OverridingNonVisibleMethod) {
0261: IMethodBinding defining = Bindings.findOverriddenMethod(
0262: method, false);
0263: if (defining != null) {
0264: int excludedModifiers = Modifier.PRIVATE
0265: | Modifier.PROTECTED | Modifier.PUBLIC;
0266: int includedModifiers = JdtFlags
0267: .getVisibilityCode(defining);
0268: String label = Messages
0269: .format(
0270: CorrectionMessages.ModifierCorrectionSubProcessor_changemethodvisibility_description,
0271: new String[] { getVisibilityString(includedModifiers) });
0272: Image image = JavaPluginImages
0273: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0274: proposals
0275: .add(new ModifierChangeCorrectionProposal(
0276: label, cu, method, selectedNode,
0277: includedModifiers, excludedModifiers,
0278: 8, image));
0279: }
0280: }
0281:
0282: IMethodBinding overriddenInClass = null;
0283: while (overriddenInClass == null
0284: && curr.getSuperclass() != null) {
0285: curr = curr.getSuperclass();
0286: overriddenInClass = Bindings.findOverriddenMethodInType(
0287: curr, method);
0288: }
0289: if (overriddenInClass != null) {
0290: IMethodBinding overriddenDecl = overriddenInClass
0291: .getMethodDeclaration();
0292: ICompilationUnit targetCU = ASTResolving
0293: .findCompilationUnitForBinding(cu, context
0294: .getASTRoot(), overriddenDecl
0295: .getDeclaringClass());
0296: if (targetCU != null) {
0297: String methodName = curr.getName() + '.'
0298: + overriddenInClass.getName();
0299: String label;
0300: int excludedModifiers;
0301: int includedModifiers;
0302: switch (kind) {
0303: case TO_VISIBLE:
0304: excludedModifiers = Modifier.PRIVATE
0305: | Modifier.PROTECTED | Modifier.PUBLIC;
0306: includedModifiers = JdtFlags
0307: .getVisibilityCode(method);
0308: label = Messages
0309: .format(
0310: CorrectionMessages.ModifierCorrectionSubProcessor_changeoverriddenvisibility_description,
0311: new String[] {
0312: methodName,
0313: getVisibilityString(includedModifiers) });
0314: break;
0315: case TO_NON_FINAL:
0316: label = Messages
0317: .format(
0318: CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononfinal_description,
0319: methodName);
0320: excludedModifiers = Modifier.FINAL;
0321: includedModifiers = 0;
0322: break;
0323: case TO_NON_STATIC:
0324: label = Messages
0325: .format(
0326: CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononstatic_description,
0327: methodName);
0328: excludedModifiers = Modifier.STATIC;
0329: includedModifiers = 0;
0330: break;
0331: default:
0332: Assert.isTrue(false, "not supported"); //$NON-NLS-1$
0333: return;
0334: }
0335: Image image = JavaPluginImages
0336: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0337: proposals
0338: .add(new ModifierChangeCorrectionProposal(
0339: label, targetCU, overriddenDecl,
0340: selectedNode, includedModifiers,
0341: excludedModifiers, 7, image));
0342: }
0343: }
0344: }
0345:
0346: public static void addNonFinalLocalProposal(
0347: IInvocationContext context, IProblemLocation problem,
0348: Collection proposals) {
0349: ICompilationUnit cu = context.getCompilationUnit();
0350:
0351: ASTNode selectedNode = problem.getCoveringNode(context
0352: .getASTRoot());
0353: if (!(selectedNode instanceof SimpleName)) {
0354: return;
0355: }
0356:
0357: IBinding binding = ((SimpleName) selectedNode).resolveBinding();
0358: if (binding instanceof IVariableBinding) {
0359: binding = ((IVariableBinding) binding)
0360: .getVariableDeclaration();
0361: Image image = JavaPluginImages
0362: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0363: String label = Messages
0364: .format(
0365: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertofinal_description,
0366: binding.getName());
0367: proposals.add(new ModifierChangeCorrectionProposal(label,
0368: cu, binding, selectedNode, Modifier.FINAL, 0, 5,
0369: image));
0370: }
0371: }
0372:
0373: public static void addRemoveInvalidModfiersProposal(
0374: IInvocationContext context, IProblemLocation problem,
0375: Collection proposals, int relevance) {
0376: ICompilationUnit cu = context.getCompilationUnit();
0377:
0378: ASTNode selectedNode = problem.getCoveringNode(context
0379: .getASTRoot());
0380: if (selectedNode instanceof MethodDeclaration) {
0381: selectedNode = ((MethodDeclaration) selectedNode).getName();
0382: }
0383:
0384: if (!(selectedNode instanceof SimpleName)) {
0385: return;
0386: }
0387:
0388: IBinding binding = ((SimpleName) selectedNode).resolveBinding();
0389: if (binding != null) {
0390: String methodName = binding.getName();
0391: String label = null;
0392: int problemId = problem.getProblemId();
0393:
0394: int excludedModifiers = 0;
0395: int includedModifiers = 0;
0396:
0397: switch (problemId) {
0398: case IProblem.CannotHideAnInstanceMethodWithAStaticMethod:
0399: case IProblem.UnexpectedStaticModifierForMethod:
0400: excludedModifiers = Modifier.STATIC;
0401: label = Messages
0402: .format(
0403: CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononstatic_description,
0404: methodName);
0405: break;
0406: case IProblem.UnexpectedStaticModifierForField:
0407: excludedModifiers = Modifier.STATIC;
0408: label = Messages
0409: .format(
0410: CorrectionMessages.ModifierCorrectionSubProcessor_changefieldmodifiertononstatic_description,
0411: methodName);
0412: break;
0413: case IProblem.IllegalModifierCombinationFinalVolatileForField:
0414: excludedModifiers = Modifier.VOLATILE;
0415: label = CorrectionMessages.ModifierCorrectionSubProcessor_removevolatile_description;
0416: break;
0417: case IProblem.IllegalModifierForInterfaceMethod:
0418: excludedModifiers = ~(Modifier.PUBLIC | Modifier.ABSTRACT);
0419: break;
0420: case IProblem.IllegalModifierForInterface:
0421: excludedModifiers = ~(Modifier.PUBLIC
0422: | Modifier.ABSTRACT | Modifier.STRICTFP);
0423: break;
0424: case IProblem.IllegalModifierForClass:
0425: excludedModifiers = ~(Modifier.PUBLIC
0426: | Modifier.ABSTRACT | Modifier.FINAL | Modifier.STRICTFP);
0427: break;
0428: case IProblem.IllegalModifierForInterfaceField:
0429: excludedModifiers = ~(Modifier.PUBLIC
0430: | Modifier.ABSTRACT | Modifier.FINAL);
0431: break;
0432: case IProblem.IllegalModifierForMemberInterface:
0433: case IProblem.IllegalVisibilityModifierForInterfaceMemberType:
0434: excludedModifiers = ~(Modifier.PUBLIC | Modifier.STATIC | Modifier.STRICTFP);
0435: break;
0436: case IProblem.IllegalModifierForMemberClass:
0437: excludedModifiers = ~(Modifier.PUBLIC
0438: | Modifier.PROTECTED | Modifier.PRIVATE
0439: | Modifier.STATIC | Modifier.ABSTRACT
0440: | Modifier.FINAL | Modifier.STRICTFP);
0441: break;
0442: case IProblem.IllegalModifierForLocalClass:
0443: excludedModifiers = ~(Modifier.ABSTRACT
0444: | Modifier.FINAL | Modifier.STRICTFP);
0445: break;
0446: case IProblem.IllegalModifierForArgument:
0447: excludedModifiers = ~Modifier.FINAL;
0448: break;
0449: case IProblem.IllegalModifierForField:
0450: excludedModifiers = ~(Modifier.PUBLIC
0451: | Modifier.PROTECTED | Modifier.PRIVATE
0452: | Modifier.STATIC | Modifier.FINAL
0453: | Modifier.VOLATILE | Modifier.TRANSIENT);
0454: break;
0455: case IProblem.IllegalModifierForMethod:
0456: excludedModifiers = ~(Modifier.PUBLIC
0457: | Modifier.PROTECTED | Modifier.PRIVATE
0458: | Modifier.STATIC | Modifier.ABSTRACT
0459: | Modifier.FINAL | Modifier.NATIVE | Modifier.STRICTFP);
0460: if (((IMethodBinding) binding).isConstructor()) {
0461: excludedModifiers |= Modifier.STATIC;
0462: }
0463: break;
0464: case IProblem.IllegalModifierForVariable:
0465: excludedModifiers = ~Modifier.FINAL;
0466: break;
0467: default:
0468: Assert.isTrue(false, "not supported"); //$NON-NLS-1$
0469: return;
0470: }
0471:
0472: if (label == null)
0473: label = Messages
0474: .format(
0475: CorrectionMessages.ModifierCorrectionSubProcessor_removeinvalidmodifiers_description,
0476: methodName);
0477:
0478: Image image = JavaPluginImages
0479: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0480: proposals.add(new ModifierChangeCorrectionProposal(label,
0481: cu, binding, selectedNode, includedModifiers,
0482: excludedModifiers, relevance, image));
0483:
0484: if (problemId == IProblem.IllegalModifierCombinationFinalVolatileForField) {
0485: proposals
0486: .add(new ModifierChangeCorrectionProposal(
0487: CorrectionMessages.ModifierCorrectionSubProcessor_removefinal_description,
0488: cu, binding, selectedNode, 0,
0489: Modifier.FINAL, relevance + 1, image));
0490: }
0491:
0492: if (problemId == IProblem.UnexpectedStaticModifierForField
0493: && binding instanceof IVariableBinding) {
0494: ITypeBinding declClass = ((IVariableBinding) binding)
0495: .getDeclaringClass();
0496: if (declClass.isMember()) {
0497: proposals
0498: .add(new ModifierChangeCorrectionProposal(
0499: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertostaticfinal_description,
0500: cu, binding, selectedNode,
0501: Modifier.FINAL, Modifier.VOLATILE,
0502: relevance + 1, image));
0503: ASTNode parentType = context.getASTRoot()
0504: .findDeclaringNode(declClass);
0505: if (parentType != null) {
0506: proposals
0507: .add(new ModifierChangeCorrectionProposal(
0508: CorrectionMessages.ModifierCorrectionSubProcessor_addstatictoparenttype_description,
0509: cu, declClass, parentType,
0510: Modifier.STATIC, 0,
0511: relevance - 1, image));
0512: }
0513: }
0514: }
0515: if (problemId == IProblem.UnexpectedStaticModifierForMethod
0516: && binding instanceof IMethodBinding) {
0517: ITypeBinding declClass = ((IMethodBinding) binding)
0518: .getDeclaringClass();
0519: if (declClass.isMember()) {
0520: ASTNode parentType = context.getASTRoot()
0521: .findDeclaringNode(declClass);
0522: if (parentType != null) {
0523: proposals
0524: .add(new ModifierChangeCorrectionProposal(
0525: CorrectionMessages.ModifierCorrectionSubProcessor_addstatictoparenttype_description,
0526: cu, declClass, parentType,
0527: Modifier.STATIC, 0,
0528: relevance - 1, image));
0529: }
0530: }
0531: }
0532: }
0533: }
0534:
0535: private static String getVisibilityString(int code) {
0536: if (Modifier.isPublic(code)) {
0537: return "public"; //$NON-NLS-1$
0538: } else if (Modifier.isProtected(code)) {
0539: return "protected"; //$NON-NLS-1$
0540: } else if (Modifier.isPrivate(code)) {
0541: return "private"; //$NON-NLS-1$
0542: }
0543: return CorrectionMessages.ModifierCorrectionSubProcessor_default;
0544: }
0545:
0546: private static int getNeededVisibility(ASTNode currNode,
0547: ITypeBinding targetType) {
0548: ITypeBinding currNodeBinding = Bindings
0549: .getBindingOfParentType(currNode);
0550: if (currNodeBinding == null) { // import
0551: return Modifier.PUBLIC;
0552: }
0553:
0554: if (Bindings.isSuperType(targetType, currNodeBinding)) {
0555: return Modifier.PROTECTED;
0556: }
0557:
0558: if (currNodeBinding.getPackage().getKey().equals(
0559: targetType.getPackage().getKey())) {
0560: return 0;
0561: }
0562: return Modifier.PUBLIC;
0563: }
0564:
0565: public static void addAbstractMethodProposals(
0566: IInvocationContext context, IProblemLocation problem,
0567: Collection proposals) {
0568: ICompilationUnit cu = context.getCompilationUnit();
0569:
0570: CompilationUnit astRoot = context.getASTRoot();
0571:
0572: ASTNode selectedNode = problem.getCoveringNode(astRoot);
0573: if (selectedNode == null) {
0574: return;
0575: }
0576: MethodDeclaration decl;
0577: if (selectedNode instanceof SimpleName) {
0578: decl = (MethodDeclaration) selectedNode.getParent();
0579: } else if (selectedNode instanceof MethodDeclaration) {
0580: decl = (MethodDeclaration) selectedNode;
0581: } else {
0582: return;
0583: }
0584:
0585: ASTNode parentType = ASTResolving.findParentType(decl);
0586: TypeDeclaration parentTypeDecl = null;
0587: boolean parentIsAbstractClass = false;
0588: if (parentType instanceof TypeDeclaration) {
0589: parentTypeDecl = (TypeDeclaration) parentType;
0590: parentIsAbstractClass = !parentTypeDecl.isInterface()
0591: && Modifier.isAbstract(parentTypeDecl
0592: .getModifiers());
0593: }
0594: boolean hasNoBody = (decl.getBody() == null);
0595:
0596: if (problem.getProblemId() == IProblem.AbstractMethodInAbstractClass
0597: || parentIsAbstractClass) {
0598: AST ast = astRoot.getAST();
0599: ASTRewrite rewrite = ASTRewrite.create(ast);
0600:
0601: Modifier modifierNode = ASTNodes.findModifierNode(
0602: Modifier.ABSTRACT, decl.modifiers());
0603: if (modifierNode != null) {
0604: rewrite.remove(modifierNode, null);
0605: }
0606:
0607: if (hasNoBody) {
0608: Block newBody = ast.newBlock();
0609: rewrite.set(decl, MethodDeclaration.BODY_PROPERTY,
0610: newBody, null);
0611:
0612: Expression expr = ASTNodeFactory.newDefaultExpression(
0613: ast, decl.getReturnType2(), decl
0614: .getExtraDimensions());
0615: if (expr != null) {
0616: ReturnStatement returnStatement = ast
0617: .newReturnStatement();
0618: returnStatement.setExpression(expr);
0619: newBody.statements().add(returnStatement);
0620: }
0621: }
0622:
0623: String label = CorrectionMessages.ModifierCorrectionSubProcessor_removeabstract_description;
0624: Image image = JavaPluginImages
0625: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0626: ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(
0627: label, cu, rewrite, 6, image);
0628: proposals.add(proposal);
0629: }
0630:
0631: if (!hasNoBody
0632: && problem.getProblemId() == IProblem.BodyForAbstractMethod) {
0633: ASTRewrite rewrite = ASTRewrite.create(decl.getAST());
0634: rewrite.remove(decl.getBody(), null);
0635:
0636: String label = CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
0637: Image image = JavaPluginImages
0638: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0639: ASTRewriteCorrectionProposal proposal2 = new ASTRewriteCorrectionProposal(
0640: label, cu, rewrite, 5, image);
0641: proposals.add(proposal2);
0642: }
0643:
0644: if (problem.getProblemId() == IProblem.AbstractMethodInAbstractClass
0645: && (parentTypeDecl != null)) {
0646: MakeTypeAbstractOperation operation = new UnimplementedCodeFix.MakeTypeAbstractOperation(
0647: parentTypeDecl);
0648:
0649: String label = Messages
0650: .format(
0651: CorrectionMessages.ModifierCorrectionSubProcessor_addabstract_description,
0652: parentTypeDecl.getName().getIdentifier());
0653: UnimplementedCodeFix fix = new UnimplementedCodeFix(label,
0654: astRoot,
0655: new CompilationUnitRewriteOperation[] { operation });
0656:
0657: Image image = JavaPluginImages
0658: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0659: FixCorrectionProposal proposal = new FixCorrectionProposal(
0660: fix, null, 5, image, context);
0661: proposals.add(proposal);
0662: }
0663:
0664: }
0665:
0666: public static void addNativeMethodProposals(
0667: IInvocationContext context, IProblemLocation problem,
0668: Collection proposals) {
0669: ICompilationUnit cu = context.getCompilationUnit();
0670:
0671: CompilationUnit astRoot = context.getASTRoot();
0672:
0673: ASTNode selectedNode = problem.getCoveringNode(astRoot);
0674: if (selectedNode == null) {
0675: return;
0676: }
0677: MethodDeclaration decl;
0678: if (selectedNode instanceof SimpleName) {
0679: decl = (MethodDeclaration) selectedNode.getParent();
0680: } else if (selectedNode instanceof MethodDeclaration) {
0681: decl = (MethodDeclaration) selectedNode;
0682: } else {
0683: return;
0684: }
0685:
0686: {
0687: AST ast = astRoot.getAST();
0688: ASTRewrite rewrite = ASTRewrite.create(ast);
0689:
0690: Modifier modifierNode = ASTNodes.findModifierNode(
0691: Modifier.NATIVE, decl.modifiers());
0692: if (modifierNode != null) {
0693: rewrite.remove(modifierNode, null);
0694: }
0695:
0696: Block newBody = ast.newBlock();
0697: rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, newBody,
0698: null);
0699:
0700: Expression expr = ASTNodeFactory.newDefaultExpression(ast,
0701: decl.getReturnType2(), decl.getExtraDimensions());
0702: if (expr != null) {
0703: ReturnStatement returnStatement = ast
0704: .newReturnStatement();
0705: returnStatement.setExpression(expr);
0706: newBody.statements().add(returnStatement);
0707: }
0708:
0709: String label = CorrectionMessages.ModifierCorrectionSubProcessor_removenative_description;
0710: Image image = JavaPluginImages
0711: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0712: ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(
0713: label, cu, rewrite, 6, image);
0714: proposals.add(proposal);
0715: }
0716:
0717: if (decl.getBody() != null) {
0718: ASTRewrite rewrite = ASTRewrite.create(decl.getAST());
0719: rewrite.remove(decl.getBody(), null);
0720:
0721: String label = CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
0722: Image image = JavaPluginImages
0723: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0724: ASTRewriteCorrectionProposal proposal2 = new ASTRewriteCorrectionProposal(
0725: label, cu, rewrite, 5, image);
0726: proposals.add(proposal2);
0727: }
0728:
0729: }
0730:
0731: public static void addMethodRequiresBodyProposals(
0732: IInvocationContext context, IProblemLocation problem,
0733: Collection proposals) {
0734: ICompilationUnit cu = context.getCompilationUnit();
0735: AST ast = context.getASTRoot().getAST();
0736:
0737: ASTNode selectedNode = problem.getCoveringNode(context
0738: .getASTRoot());
0739: if (!(selectedNode instanceof MethodDeclaration)) {
0740: return;
0741: }
0742: MethodDeclaration decl = (MethodDeclaration) selectedNode;
0743: {
0744: ASTRewrite rewrite = ASTRewrite.create(ast);
0745:
0746: Modifier modifierNode = ASTNodes.findModifierNode(
0747: Modifier.ABSTRACT, decl.modifiers());
0748: if (modifierNode != null) {
0749: rewrite.remove(modifierNode, null);
0750: }
0751:
0752: Block body = ast.newBlock();
0753: rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, body,
0754: null);
0755:
0756: if (!decl.isConstructor()) {
0757: Type returnType = decl.getReturnType2();
0758: Expression expression = ASTNodeFactory
0759: .newDefaultExpression(ast, returnType, decl
0760: .getExtraDimensions());
0761: if (expression != null) {
0762: ReturnStatement returnStatement = ast
0763: .newReturnStatement();
0764: returnStatement.setExpression(expression);
0765: body.statements().add(returnStatement);
0766: }
0767: }
0768:
0769: String label = CorrectionMessages.ModifierCorrectionSubProcessor_addmissingbody_description;
0770: Image image = JavaPluginImages
0771: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0772: ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(
0773: label, cu, rewrite, 9, image);
0774:
0775: proposals.add(proposal);
0776: }
0777: {
0778: ASTRewrite rewrite = ASTRewrite.create(ast);
0779:
0780: Modifier newModifier = ast
0781: .newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
0782: rewrite.getListRewrite(decl,
0783: MethodDeclaration.MODIFIERS2_PROPERTY).insertLast(
0784: newModifier, null);
0785:
0786: String label = CorrectionMessages.ModifierCorrectionSubProcessor_setmethodabstract_description;
0787: Image image = JavaPluginImages
0788: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0789: LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(
0790: label, cu, rewrite, 8, image);
0791: proposal.addLinkedPosition(rewrite.track(newModifier),
0792: true, "modifier"); //$NON-NLS-1$
0793:
0794: proposals.add(proposal);
0795: }
0796:
0797: }
0798:
0799: public static void addNeedToEmulateProposal(
0800: IInvocationContext context, IProblemLocation problem,
0801: Collection proposals) {
0802: ICompilationUnit cu = context.getCompilationUnit();
0803:
0804: ASTNode selectedNode = problem.getCoveringNode(context
0805: .getASTRoot());
0806: if (!(selectedNode instanceof SimpleName)) {
0807: return;
0808: }
0809:
0810: IBinding binding = ((SimpleName) selectedNode).resolveBinding();
0811: if (binding instanceof IVariableBinding) {
0812: binding = ((IVariableBinding) binding)
0813: .getVariableDeclaration();
0814: Image image = JavaPluginImages
0815: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0816: String label = Messages
0817: .format(
0818: CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertofinal_description,
0819: binding.getName());
0820: proposals.add(new ModifierChangeCorrectionProposal(label,
0821: cu, binding, selectedNode, Modifier.FINAL, 0, 5,
0822: image));
0823: }
0824: }
0825:
0826: public static void addOverrideAnnotationProposal(
0827: IInvocationContext context, IProblemLocation problem,
0828: Collection proposals) throws CoreException {
0829: IProposableFix fix = Java50Fix.createAddOverrideAnnotationFix(
0830: context.getASTRoot(), problem);
0831: if (fix != null) {
0832: Image image = JavaPluginImages
0833: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0834: Map options = new Hashtable();
0835: options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS,
0836: CleanUpConstants.TRUE);
0837: options.put(
0838: CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE,
0839: CleanUpConstants.TRUE);
0840: FixCorrectionProposal proposal = new FixCorrectionProposal(
0841: fix, new Java50CleanUp(options), 5, image, context);
0842: proposals.add(proposal);
0843: }
0844: }
0845:
0846: public static void addDeprecatedAnnotationProposal(
0847: IInvocationContext context, IProblemLocation problem,
0848: Collection proposals) throws CoreException {
0849: IProposableFix fix = Java50Fix.createAddDeprectatedAnnotation(
0850: context.getASTRoot(), problem);
0851: if (fix != null) {
0852: Image image = JavaPluginImages
0853: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0854: Map options = new Hashtable();
0855: options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS,
0856: CleanUpConstants.TRUE);
0857: options
0858: .put(
0859: CleanUpConstants.ADD_MISSING_ANNOTATIONS_DEPRECATED,
0860: CleanUpConstants.TRUE);
0861: FixCorrectionProposal proposal = new FixCorrectionProposal(
0862: fix, new Java50CleanUp(options), 5, image, context);
0863: proposals.add(proposal);
0864: }
0865: }
0866:
0867: public static void addOverridingDeprecatedMethodProposal(
0868: IInvocationContext context, IProblemLocation problem,
0869: Collection proposals) throws CoreException {
0870:
0871: ICompilationUnit cu = context.getCompilationUnit();
0872:
0873: ASTNode selectedNode = problem.getCoveringNode(context
0874: .getASTRoot());
0875: if (!(selectedNode instanceof MethodDeclaration)) {
0876: return;
0877: }
0878: boolean is50OrHigher = JavaModelUtil.is50OrHigher(cu
0879: .getJavaProject());
0880: MethodDeclaration methodDecl = (MethodDeclaration) selectedNode;
0881: AST ast = methodDecl.getAST();
0882: ASTRewrite rewrite = ASTRewrite.create(ast);
0883: if (is50OrHigher) {
0884: Annotation annot = ast.newMarkerAnnotation();
0885: annot.setTypeName(ast.newName("Deprecated")); //$NON-NLS-1$
0886: rewrite.getListRewrite(methodDecl,
0887: methodDecl.getModifiersProperty()).insertFirst(
0888: annot, null);
0889: }
0890: Javadoc javadoc = methodDecl.getJavadoc();
0891: if (javadoc != null || !is50OrHigher) {
0892: if (!is50OrHigher) {
0893: javadoc = ast.newJavadoc();
0894: rewrite.set(methodDecl,
0895: MethodDeclaration.JAVADOC_PROPERTY, javadoc,
0896: null);
0897: }
0898: TagElement newTag = ast.newTagElement();
0899: newTag.setTagName(TagElement.TAG_DEPRECATED);
0900: JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(
0901: javadoc, Javadoc.TAGS_PROPERTY), newTag, null);
0902: }
0903:
0904: String label = CorrectionMessages.ModifierCorrectionSubProcessor_overrides_deprecated_description;
0905: Image image = JavaPluginImages
0906: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0907: ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(
0908: label, cu, rewrite, 15, image);
0909: proposals.add(proposal);
0910: }
0911:
0912: public static void removeOverrideAnnotationProposal(
0913: IInvocationContext context, IProblemLocation problem,
0914: Collection proposals) throws CoreException {
0915: ICompilationUnit cu = context.getCompilationUnit();
0916:
0917: ASTNode selectedNode = problem.getCoveringNode(context
0918: .getASTRoot());
0919: if (!(selectedNode instanceof MethodDeclaration)) {
0920: return;
0921: }
0922: MethodDeclaration methodDecl = (MethodDeclaration) selectedNode;
0923: Annotation annot = findAnnotation(
0924: "java.lang.Override", methodDecl.modifiers()); //$NON-NLS-1$
0925: if (annot != null) {
0926: ASTRewrite rewrite = ASTRewrite.create(annot.getAST());
0927: rewrite.remove(annot, null);
0928: String label = CorrectionMessages.ModifierCorrectionSubProcessor_remove_override;
0929: Image image = JavaPluginImages
0930: .get(JavaPluginImages.IMG_CORRECTION_CHANGE);
0931: ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(
0932: label, cu, rewrite, 6, image);
0933: proposals.add(proposal);
0934:
0935: QuickAssistProcessor.getCreateInSuperClassProposals(
0936: context, methodDecl.getName(), proposals);
0937: }
0938: }
0939:
0940: private static final String KEY_MODIFIER = "modifier"; //$NON-NLS-1$
0941:
0942: private static class ModifierLinkedModeProposal extends
0943: LinkedProposalPositionGroup.Proposal {
0944:
0945: private final int fModifier;
0946:
0947: public ModifierLinkedModeProposal(int modifier, int relevance) {
0948: super (null, null, relevance);
0949: fModifier = modifier;
0950: }
0951:
0952: public String getAdditionalProposalInfo() {
0953: return getDisplayString();
0954: }
0955:
0956: public String getDisplayString() {
0957: if (fModifier == 0) {
0958: return CorrectionMessages.ModifierCorrectionSubProcessor_default_visibility_label;
0959: } else {
0960: return ModifierKeyword.fromFlagValue(fModifier)
0961: .toString();
0962: }
0963: }
0964:
0965: /* (non-Javadoc)
0966: * @see org.eclipse.jdt.internal.corext.fix.PositionGroup.Proposal#computeEdits(int, org.eclipse.jface.text.link.LinkedPosition, char, int, org.eclipse.jface.text.link.LinkedModeModel)
0967: */
0968: public TextEdit computeEdits(int offset,
0969: LinkedPosition currentPosition, char trigger,
0970: int stateMask, LinkedModeModel model)
0971: throws CoreException {
0972: try {
0973: IDocument document = currentPosition.getDocument();
0974: MultiTextEdit edit = new MultiTextEdit();
0975: int documentLen = document.getLength();
0976: if (fModifier == 0) {
0977: int end = currentPosition.offset
0978: + currentPosition.length; // current end position
0979: int k = end;
0980: while (k < documentLen
0981: && IndentManipulation.isIndentChar(document
0982: .getChar(k))) {
0983: k++;
0984: }
0985: // first remove space then replace range (remove space can destroy empty position)
0986: edit.addChild(new ReplaceEdit(end, k - end,
0987: new String())); // remove extra spaces
0988: edit.addChild(new ReplaceEdit(
0989: currentPosition.offset,
0990: currentPosition.length, new String()));
0991: } else {
0992: // first then replace range the insert space (insert space can destroy empty position)
0993: edit.addChild(new ReplaceEdit(
0994: currentPosition.offset,
0995: currentPosition.length, ModifierKeyword
0996: .fromFlagValue(fModifier)
0997: .toString()));
0998: int end = currentPosition.offset
0999: + currentPosition.length; // current end position
1000: if (end < documentLen
1001: && !Character.isWhitespace(document
1002: .getChar(end))) {
1003: edit.addChild(new ReplaceEdit(end, 0, String
1004: .valueOf(' '))); // insert extra space
1005: }
1006: }
1007: return edit;
1008: } catch (BadLocationException e) {
1009: throw new CoreException(new Status(IStatus.ERROR,
1010: JavaUI.ID_PLUGIN, IStatus.ERROR,
1011: e.getMessage(), e));
1012: }
1013: }
1014: }
1015:
1016: public static void installLinkedVisibilityProposals(
1017: LinkedProposalModel linkedProposalModel,
1018: ASTRewrite rewrite, List modifiers, boolean inInterface) {
1019: ASTNode modifier = findVisibilityModifier(modifiers);
1020: if (modifier != null) {
1021: int selected = ((Modifier) modifier).getKeyword()
1022: .toFlagValue();
1023:
1024: LinkedProposalPositionGroup positionGroup = linkedProposalModel
1025: .getPositionGroup(KEY_MODIFIER, true);
1026: positionGroup.addPosition(rewrite.track(modifier), false);
1027: positionGroup.addProposal(new ModifierLinkedModeProposal(
1028: selected, 10));
1029:
1030: // add all others
1031: int[] flagValues = inInterface ? new int[] {
1032: Modifier.PUBLIC, 0 } : new int[] { Modifier.PUBLIC,
1033: 0, Modifier.PROTECTED, Modifier.PRIVATE };
1034: for (int i = 0; i < flagValues.length; i++) {
1035: if (flagValues[i] != selected) {
1036: positionGroup
1037: .addProposal(new ModifierLinkedModeProposal(
1038: flagValues[i], 9 - i));
1039: }
1040: }
1041: }
1042: }
1043:
1044: private static Modifier findVisibilityModifier(List modifiers) {
1045: for (int i = 0; i < modifiers.size(); i++) {
1046: Object curr = modifiers.get(i);
1047: if (curr instanceof Modifier) {
1048: Modifier modifier = (Modifier) curr;
1049: ModifierKeyword keyword = modifier.getKeyword();
1050: if (keyword == ModifierKeyword.PUBLIC_KEYWORD
1051: || keyword == ModifierKeyword.PROTECTED_KEYWORD
1052: || keyword == ModifierKeyword.PRIVATE_KEYWORD) {
1053: return modifier;
1054: }
1055: }
1056: }
1057: return null;
1058: }
1059:
1060: private static Annotation findAnnotation(String qualifiedTypeName,
1061: List modifiers) {
1062: for (int i = 0; i < modifiers.size(); i++) {
1063: Object curr = modifiers.get(i);
1064: if (curr instanceof Annotation) {
1065: Annotation annot = (Annotation) curr;
1066: ITypeBinding binding = annot.getTypeName()
1067: .resolveTypeBinding();
1068: if (binding != null
1069: && qualifiedTypeName.equals(binding
1070: .getQualifiedName())) {
1071: return annot;
1072: }
1073: }
1074: }
1075: return null;
1076: }
1077:
1078: }
|