/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Benjamin Muskalla <bmuskalla@innoopract.com> - [quick fix] 'Remove invalid modifiers' does not appear for enums and annotations -
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=110589
* Benjamin Muskalla <b.muskalla@gmx.net> - [quick fix] Quick fix for missing synchronized modifier - https://bugs.eclipse
* .org/bugs/show_bug.cgi?id=245250
*******************************************************************************/
package org.eclipse.che.ide.ext.java.jdt.internal.text.correction;
import org.eclipse.che.ide.ext.java.jdt.Images;
import org.eclipse.che.ide.ext.java.jdt.codeassistant.api.IProblemLocation;
import org.eclipse.che.ide.ext.java.jdt.core.compiler.IProblem;
import org.eclipse.che.ide.ext.java.jdt.core.dom.AST;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTNode;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Annotation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Block;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Expression;
import org.eclipse.che.ide.ext.java.jdt.core.dom.FieldAccess;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IExtendedModifier;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IMethodBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ITypeBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IVariableBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Javadoc;
import org.eclipse.che.ide.ext.java.jdt.core.dom.MethodDeclaration;
import org.eclipse.che.ide.ext.java.jdt.core.dom.MethodInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Modifier;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.che.ide.ext.java.jdt.core.dom.QualifiedName;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ReturnStatement;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SimpleName;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SimpleType;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SuperFieldAccess;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.TagElement;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Type;
import org.eclipse.che.ide.ext.java.jdt.core.dom.TypeDeclaration;
import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.codemanipulation.ASTResolving;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.Bindings;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.fix.UnimplementedCodeFix;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.fix.UnimplementedCodeFix.MakeTypeAbstractOperation;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.util.JdtFlags;
import org.eclipse.che.ide.ext.java.jdt.internal.text.correction.proposals.ASTRewriteCorrectionProposal;
import org.eclipse.che.ide.ext.java.jdt.internal.text.correction.proposals.FixCorrectionProposal;
import org.eclipse.che.ide.ext.java.jdt.internal.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.che.ide.ext.java.jdt.internal.text.correction.proposals.ModifierChangeCorrectionProposal;
import org.eclipse.che.ide.ext.java.jdt.quickassist.api.InvocationContext;
import org.eclipse.che.ide.runtime.Assert;
import org.eclipse.che.ide.runtime.CoreException;
import java.util.Collection;
import java.util.List;
/**
*/
public class ModifierCorrectionSubProcessor {
public static final int TO_STATIC = 1;
public static final int TO_VISIBLE = 2;
public static final int TO_NON_PRIVATE = 3;
public static final int TO_NON_STATIC = 4;
public static final int TO_NON_FINAL = 5;
public static void addNonAccessibleReferenceProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals, int kind, int relevance)
throws CoreException {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
IBinding binding = null;
switch (selectedNode.getNodeType()) {
case ASTNode.SIMPLE_NAME:
binding = ((SimpleName)selectedNode).resolveBinding();
break;
case ASTNode.QUALIFIED_NAME:
binding = ((QualifiedName)selectedNode).resolveBinding();
break;
case ASTNode.SIMPLE_TYPE:
binding = ((SimpleType)selectedNode).resolveBinding();
break;
case ASTNode.METHOD_INVOCATION:
binding = ((MethodInvocation)selectedNode).getName().resolveBinding();
break;
case ASTNode.SUPER_METHOD_INVOCATION:
binding = ((SuperMethodInvocation)selectedNode).getName().resolveBinding();
break;
case ASTNode.FIELD_ACCESS:
binding = ((FieldAccess)selectedNode).getName().resolveBinding();
break;
case ASTNode.SUPER_FIELD_ACCESS:
binding = ((SuperFieldAccess)selectedNode).getName().resolveBinding();
break;
case ASTNode.CLASS_INSTANCE_CREATION:
binding = ((ClassInstanceCreation)selectedNode).resolveConstructorBinding();
break;
case ASTNode.SUPER_CONSTRUCTOR_INVOCATION:
binding = ((SuperConstructorInvocation)selectedNode).resolveConstructorBinding();
break;
default:
return;
}
ITypeBinding typeBinding = null;
String name;
IBinding bindingDecl;
boolean isLocalVar = false;
if (binding instanceof IVariableBinding && problem.getProblemId() == IProblem.NotVisibleType) {
binding = ((IVariableBinding)binding).getType();
}
if (binding instanceof IMethodBinding) {
IMethodBinding methodDecl = (IMethodBinding)binding;
if (methodDecl.isDefaultConstructor()) {
UnresolvedElementsSubProcessor.getConstructorProposals(context, problem, proposals);
return;
}
bindingDecl = methodDecl.getMethodDeclaration();
typeBinding = methodDecl.getDeclaringClass();
name = methodDecl.getName() + "()"; //$NON-NLS-1$
} else if (binding instanceof IVariableBinding) {
IVariableBinding varDecl = (IVariableBinding)binding;
typeBinding = varDecl.getDeclaringClass();
name = binding.getName();
isLocalVar = !varDecl.isField();
bindingDecl = varDecl.getVariableDeclaration();
} else if (binding instanceof ITypeBinding) {
typeBinding = (ITypeBinding)binding;
bindingDecl = typeBinding.getTypeDeclaration();
name = binding.getName();
} else {
return;
}
if (typeBinding != null && typeBinding.isFromSource() || isLocalVar) {
int includedModifiers = 0;
int excludedModifiers = 0;
String label;
switch (kind) {
case TO_VISIBLE:
excludedModifiers = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
includedModifiers = getNeededVisibility(selectedNode, typeBinding);
label =
CorrectionMessages.INSTANCE.INSTANCE.ModifierCorrectionSubProcessor_changevisibility_description(
name, getVisibilityString(includedModifiers));
break;
case TO_STATIC:
label =
CorrectionMessages.INSTANCE.INSTANCE
.ModifierCorrectionSubProcessor_changemodifiertostatic_description(name);
includedModifiers = Modifier.STATIC;
break;
case TO_NON_STATIC:
label =
CorrectionMessages.INSTANCE.INSTANCE
.ModifierCorrectionSubProcessor_changemodifiertononstatic_description(name);
excludedModifiers = Modifier.STATIC;
break;
case TO_NON_PRIVATE:
int visibility;
if (context.getASTRoot().getPackage().getName().getFullyQualifiedName()
.equals(typeBinding.getPackage().getName()))
// if (cu.getParent().getElementName().equals())
{
visibility = Modifier.NONE;
excludedModifiers = Modifier.PRIVATE;
} else {
visibility = Modifier.PUBLIC;
includedModifiers = Modifier.PUBLIC;
excludedModifiers = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
}
label =
CorrectionMessages.INSTANCE.INSTANCE.ModifierCorrectionSubProcessor_changevisibility_description(
name, getVisibilityString(visibility));
break;
case TO_NON_FINAL:
label =
CorrectionMessages.INSTANCE.INSTANCE
.ModifierCorrectionSubProcessor_changemodifiertononfinal_description(name);
excludedModifiers = Modifier.FINAL;
break;
default:
throw new IllegalArgumentException("not supported"); //$NON-NLS-1$
}
//TODO load class
// ICompilationUnit targetCU =
// isLocalVar ? cu : ASTResolving.findCompilationUnitForBinding(cu, context.getASTRoot(),
// typeBinding.getTypeDeclaration());
// if (targetCU != null)
// {
// Image image = new Image(JavaClientBundle.INSTANCE.correction_change());
// proposals.add(new ModifierChangeCorrectionProposal(label, bindingDecl, selectedNode, includedModifiers,
// excludedModifiers, relevance, context.getDocument(), image));
// }
}
if (kind == TO_VISIBLE && bindingDecl.getKind() == IBinding.VARIABLE) {
UnresolvedElementsSubProcessor
.getVariableProposals(context, problem, (IVariableBinding)bindingDecl, proposals);
}
}
public static void addChangeOverriddenModifierProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals, int kind) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof MethodDeclaration)) {
return;
}
IMethodBinding method = ((MethodDeclaration)selectedNode).resolveBinding();
ITypeBinding curr = method.getDeclaringClass();
if (kind == TO_VISIBLE && problem.getProblemId() != IProblem.OverridingNonVisibleMethod) {
IMethodBinding defining = Bindings.findOverriddenMethod(method, false);
if (defining != null) {
int excludedModifiers = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
int includedModifiers = JdtFlags.getVisibilityCode(defining);
String label =
CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_changemethodvisibility_description(
getVisibilityString(includedModifiers));
Images image = Images.correction_change;
proposals.add(new ModifierChangeCorrectionProposal(label, method, selectedNode, includedModifiers,
excludedModifiers, 8, context.getDocument(), image));
}
}
IMethodBinding overriddenInClass = null;
while (overriddenInClass == null && curr.getSuperclass() != null) {
curr = curr.getSuperclass();
overriddenInClass = Bindings.findOverriddenMethodInType(curr, method);
}
if (overriddenInClass != null) {
//TODO
//IMethodBinding overriddenDecl = overriddenInClass.getMethodDeclaration();
// ICompilationUnit targetCU =
// ASTResolving.findCompilationUnitForBinding(cu, context.getASTRoot(), overriddenDecl.getDeclaringClass());
// if (targetCU != null)
// {
// String methodLabel = curr.getName() + '.' + overriddenInClass.getName();
// String label;
// int excludedModifiers;
// int includedModifiers;
// switch (kind)
// {
// case TO_VISIBLE :
// excludedModifiers = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
// includedModifiers = JdtFlags.getVisibilityCode(method);
// label =
// CorrectionMessages.INSTANCE.INSTANCE
// .ModifierCorrectionSubProcessor_changeoverriddenvisibility_description(methodLabel,
// getVisibilityString(includedModifiers));
// break;
// case TO_NON_FINAL :
// label =
// CorrectionMessages.INSTANCE.INSTANCE
// .ModifierCorrectionSubProcessor_changemethodtononfinal_description(methodLabel);
// excludedModifiers = Modifier.FINAL;
// includedModifiers = 0;
// break;
// case TO_NON_STATIC :
// label =
// CorrectionMessages.INSTANCE.INSTANCE
// .ModifierCorrectionSubProcessor_changemethodtononstatic_description(methodLabel);
// excludedModifiers = Modifier.STATIC;
// includedModifiers = 0;
// break;
// default :
// Assert.isTrue(false, "not supported"); //$NON-NLS-1$
// return;
// }
// Image image = new Image(JavaClientBundle.INSTANCE.correction_change());
// proposals.add(new ModifierChangeCorrectionProposal(label, overriddenDecl, selectedNode, includedModifiers,
// excludedModifiers, 7, context.getDocument(), image));
// }
}
}
public static void addNonFinalLocalProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof SimpleName)) {
return;
}
IBinding binding = ((SimpleName)selectedNode).resolveBinding();
if (binding instanceof IVariableBinding) {
binding = ((IVariableBinding)binding).getVariableDeclaration();
Images image = Images.correction_change;
String label =
CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_changemodifiertofinal_description(binding
.getName());
proposals.add(new ModifierChangeCorrectionProposal(label, binding, selectedNode, Modifier.FINAL, 0, 5, context
.getDocument(), image));
}
}
public static void addRemoveInvalidModifiersProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals, int relevance) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof MethodDeclaration) {
selectedNode = ((MethodDeclaration)selectedNode).getName();
}
if (!(selectedNode instanceof SimpleName)) {
return;
}
IBinding binding = ((SimpleName)selectedNode).resolveBinding();
if (binding != null) {
String methodName = binding.getName();
String label = null;
int problemId = problem.getProblemId();
int excludedModifiers = 0;
int includedModifiers = 0;
switch (problemId) {
case IProblem.CannotHideAnInstanceMethodWithAStaticMethod:
case IProblem.UnexpectedStaticModifierForMethod:
excludedModifiers = Modifier.STATIC;
label =
CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_changemethodtononstatic_description(methodName);
break;
case IProblem.UnexpectedStaticModifierForField:
excludedModifiers = Modifier.STATIC;
label =
CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_changefieldmodifiertononstatic_description(methodName);
break;
case IProblem.IllegalModifierCombinationFinalVolatileForField:
excludedModifiers = Modifier.VOLATILE;
label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_removevolatile_description();
break;
case IProblem.IllegalModifierForInterfaceMethod:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.ABSTRACT);
break;
case IProblem.IllegalModifierForInterface:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForClass:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForInterfaceField:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
break;
case IProblem.IllegalModifierForMemberInterface:
case IProblem.IllegalVisibilityModifierForInterfaceMemberType:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.STATIC | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForMemberClass:
excludedModifiers =
~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC | Modifier.ABSTRACT
| Modifier.FINAL | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForLocalClass:
excludedModifiers = ~(Modifier.ABSTRACT | Modifier.FINAL | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForArgument:
excludedModifiers = ~Modifier.FINAL;
break;
case IProblem.IllegalModifierForField:
excludedModifiers =
~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL
| Modifier.VOLATILE | Modifier.TRANSIENT);
break;
case IProblem.IllegalModifierForMethod:
excludedModifiers =
~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC | Modifier.ABSTRACT
| Modifier.FINAL | Modifier.NATIVE | Modifier.STRICTFP | Modifier.SYNCHRONIZED);
break;
case IProblem.IllegalModifierForConstructor:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);
break;
case IProblem.IllegalModifierForVariable:
excludedModifiers = ~Modifier.FINAL;
break;
case IProblem.IllegalModifierForEnum:
excludedModifiers = ~(Modifier.PUBLIC | Modifier.STRICTFP);
break;
case IProblem.IllegalModifierForEnumConstant:
excludedModifiers = ~Modifier.NONE;
break;
case IProblem.IllegalModifierForEnumConstructor:
excludedModifiers = ~Modifier.PRIVATE;
break;
case IProblem.IllegalModifierForMemberEnum:
excludedModifiers =
~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.STRICTFP);
break;
default:
Assert.isTrue(false, "not supported"); //$NON-NLS-1$
return;
}
if (label == null)
label =
CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_removeinvalidmodifiers_description(methodName);
Images image = Images.correction_change;
proposals.add(new ModifierChangeCorrectionProposal(label, binding, selectedNode, includedModifiers,
excludedModifiers, relevance, context.getDocument(), image));
if (problemId == IProblem.IllegalModifierCombinationFinalVolatileForField) {
proposals.add(new ModifierChangeCorrectionProposal(CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_removefinal_description(),
binding, selectedNode, 0, Modifier.FINAL,
relevance + 1, context.getDocument(), image));
}
if (problemId == IProblem.UnexpectedStaticModifierForField && binding instanceof IVariableBinding) {
ITypeBinding declClass = ((IVariableBinding)binding).getDeclaringClass();
if (declClass.isMember()) {
proposals.add(new ModifierChangeCorrectionProposal(CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_changemodifiertostaticfinal_description(),
binding, selectedNode,
Modifier.FINAL, Modifier.VOLATILE, relevance + 1,
context.getDocument(), image));
ASTNode parentType = context.getASTRoot().findDeclaringNode(declClass);
if (parentType != null) {
proposals.add(new ModifierChangeCorrectionProposal(CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_addstatictoparenttype_description(),
declClass, parentType,
Modifier.STATIC, 0, relevance - 1, context.getDocument(),
image));
}
}
}
if (problemId == IProblem.UnexpectedStaticModifierForMethod && binding instanceof IMethodBinding) {
ITypeBinding declClass = ((IMethodBinding)binding).getDeclaringClass();
if (declClass.isMember()) {
ASTNode parentType = context.getASTRoot().findDeclaringNode(declClass);
if (parentType != null) {
proposals.add(new ModifierChangeCorrectionProposal(CorrectionMessages.INSTANCE
.ModifierCorrectionSubProcessor_addstatictoparenttype_description(),
declClass, parentType,
Modifier.STATIC, 0, relevance - 1, context.getDocument(),
image));
}
}
}
}
}
private static String getVisibilityString(int code) {
if (Modifier.isPublic(code)) {
return "public"; //$NON-NLS-1$
} else if (Modifier.isProtected(code)) {
return "protected"; //$NON-NLS-1$
} else if (Modifier.isPrivate(code)) {
return "private"; //$NON-NLS-1$
}
return CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_default();
}
private static int getNeededVisibility(ASTNode currNode, ITypeBinding targetType) {
ITypeBinding currNodeBinding = Bindings.getBindingOfParentType(currNode);
if (currNodeBinding == null) { // import
return Modifier.PUBLIC;
}
if (Bindings.isSuperType(targetType, currNodeBinding)) {
return Modifier.PROTECTED;
}
if (currNodeBinding.getPackage().getKey().equals(targetType.getPackage().getKey())) {
return 0;
}
return Modifier.PUBLIC;
}
public static void addAbstractMethodProposals(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
CompilationUnit astRoot = context.getASTRoot();
ASTNode selectedNode = problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
MethodDeclaration decl;
if (selectedNode instanceof SimpleName) {
decl = (MethodDeclaration)selectedNode.getParent();
} else if (selectedNode instanceof MethodDeclaration) {
decl = (MethodDeclaration)selectedNode;
} else {
return;
}
ASTNode parentType = ASTResolving.findParentType(decl);
TypeDeclaration parentTypeDecl = null;
boolean parentIsAbstractClass = false;
if (parentType instanceof TypeDeclaration) {
parentTypeDecl = (TypeDeclaration)parentType;
parentIsAbstractClass = !parentTypeDecl.isInterface() && Modifier.isAbstract(parentTypeDecl.getModifiers());
}
boolean hasNoBody = decl.getBody() == null;
int id = problem.getProblemId();
if (id == IProblem.AbstractMethodInAbstractClass || id == IProblem.EnumAbstractMethodMustBeImplemented
|| id == IProblem.AbstractMethodInEnum || parentIsAbstractClass) {
AST ast = astRoot.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
Modifier modifierNode = ASTNodes.findModifierNode(Modifier.ABSTRACT, decl.modifiers());
if (modifierNode != null) {
rewrite.remove(modifierNode, null);
}
if (hasNoBody) {
Block newBody = ast.newBlock();
rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, newBody, null);
Type returnType = decl.getReturnType2();
if (returnType != null) {
Expression expr = ASTNodeFactory.newDefaultExpression(ast, returnType, decl.getExtraDimensions());
if (expr != null) {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expr);
newBody.statements().add(returnStatement);
}
}
}
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_removeabstract_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal =
new ASTRewriteCorrectionProposal(label, rewrite, 6, context.getDocument(), image);
proposals.add(proposal);
}
if (!hasNoBody && id == IProblem.BodyForAbstractMethod) {
ASTRewrite rewrite = ASTRewrite.create(decl.getAST());
rewrite.remove(decl.getBody(), null);
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_removebody_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal2 =
new ASTRewriteCorrectionProposal(label, rewrite, 5, context.getDocument(), image);
proposals.add(proposal2);
}
if (id == IProblem.AbstractMethodInAbstractClass && parentTypeDecl != null) {
addMakeTypeAbstractProposal(context, parentTypeDecl, proposals);
}
}
private static void addMakeTypeAbstractProposal(InvocationContext context, TypeDeclaration parentTypeDecl,
Collection<ICommandAccess> proposals) {
MakeTypeAbstractOperation operation = new UnimplementedCodeFix.MakeTypeAbstractOperation(parentTypeDecl);
String label =
CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_addabstract_description(parentTypeDecl.getName()
.getIdentifier());
UnimplementedCodeFix fix =
new UnimplementedCodeFix(label, context.getASTRoot(), new CompilationUnitRewriteOperation[]{operation},
context.getDocument());
Images image = Images.correction_change;
FixCorrectionProposal proposal = new FixCorrectionProposal(fix, null, 5, image, context);
proposals.add(proposal);
}
public static void addAbstractTypeProposals(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
CompilationUnit astRoot = context.getASTRoot();
ASTNode selectedNode = problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
TypeDeclaration parentTypeDecl = null;
if (selectedNode instanceof SimpleName) {
ASTNode parent = selectedNode.getParent();
if (parent != null) {
parentTypeDecl = (TypeDeclaration)parent;
}
} else if (selectedNode instanceof TypeDeclaration) {
parentTypeDecl = (TypeDeclaration)selectedNode;
}
if (parentTypeDecl == null) {
return;
}
addMakeTypeAbstractProposal(context, parentTypeDecl, proposals);
}
public static void addNativeMethodProposals(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
CompilationUnit astRoot = context.getASTRoot();
ASTNode selectedNode = problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
MethodDeclaration decl;
if (selectedNode instanceof SimpleName) {
decl = (MethodDeclaration)selectedNode.getParent();
} else if (selectedNode instanceof MethodDeclaration) {
decl = (MethodDeclaration)selectedNode;
} else {
return;
}
{
AST ast = astRoot.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
Modifier modifierNode = ASTNodes.findModifierNode(Modifier.NATIVE, decl.modifiers());
if (modifierNode != null) {
rewrite.remove(modifierNode, null);
}
Block newBody = ast.newBlock();
rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, newBody, null);
Type returnType = decl.getReturnType2();
if (returnType != null) {
Expression expr = ASTNodeFactory.newDefaultExpression(ast, returnType, decl.getExtraDimensions());
if (expr != null) {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expr);
newBody.statements().add(returnStatement);
}
}
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_removenative_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal =
new ASTRewriteCorrectionProposal(label, rewrite, 6, context.getDocument(), image);
proposals.add(proposal);
}
if (decl.getBody() != null) {
ASTRewrite rewrite = ASTRewrite.create(decl.getAST());
rewrite.remove(decl.getBody(), null);
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_removebody_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal2 =
new ASTRewriteCorrectionProposal(label, rewrite, 5, context.getDocument(), image);
proposals.add(proposal2);
}
}
public static void addMethodRequiresBodyProposals(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
AST ast = context.getASTRoot().getAST();
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof MethodDeclaration)) {
return;
}
MethodDeclaration decl = (MethodDeclaration)selectedNode;
Modifier modifierNode = ASTNodes.findModifierNode(Modifier.ABSTRACT, decl.modifiers());
{
ASTRewrite rewrite = ASTRewrite.create(ast);
if (modifierNode != null) {
rewrite.remove(modifierNode, null);
}
Block body = ast.newBlock();
rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, body, null);
if (!decl.isConstructor()) {
Type returnType = decl.getReturnType2();
if (returnType != null) {
Expression expression = ASTNodeFactory.newDefaultExpression(ast, returnType, decl.getExtraDimensions());
if (expression != null) {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expression);
body.statements().add(returnStatement);
}
}
}
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_addmissingbody_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal =
new ASTRewriteCorrectionProposal(label, rewrite, 9, context.getDocument(), image);
proposals.add(proposal);
}
if (modifierNode == null) {
ASTRewrite rewrite = ASTRewrite.create(ast);
Modifier newModifier = ast.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
rewrite.getListRewrite(decl, MethodDeclaration.MODIFIERS2_PROPERTY).insertLast(newModifier, null);
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_setmethodabstract_description();
Images image = Images.correction_change;
LinkedCorrectionProposal proposal =
new LinkedCorrectionProposal(label, rewrite, 8, context.getDocument(), image);
// proposal.addLinkedPosition(rewrite.track(newModifier), true, "modifier"); //$NON-NLS-1$
proposals.add(proposal);
}
}
public static void addNeedToEmulateProposal(InvocationContext context, IProblemLocation problem,
Collection<ModifierChangeCorrectionProposal> proposals) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof SimpleName)) {
return;
}
IBinding binding = ((SimpleName)selectedNode).resolveBinding();
if (binding instanceof IVariableBinding) {
binding = ((IVariableBinding)binding).getVariableDeclaration();
Images image = Images.correction_change;
String label =
CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_changemodifiertofinal_description(binding
.getName());
proposals.add(new ModifierChangeCorrectionProposal(label, binding, selectedNode, Modifier.FINAL, 0, 5, context
.getDocument(), image));
}
}
public static void addOverrideAnnotationProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
System.out.println("ModifierCorrectionSubProcessor.addOverrideAnnotationProposal()");
//TODO
// IProposableFix fix = Java50Fix.createAddOverrideAnnotationFix(context.getASTRoot(), problem);
// if (fix != null)
// {
// Image image = new Image(JavaClientBundle.INSTANCE.correction_change());
// Map<String, String> options = new HashMap<String, String>();
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS, CleanUpOptions.TRUE);
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE, CleanUpOptions.TRUE);
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE_FOR_INTERFACE_METHOD_IMPLEMENTATION,
// CleanUpOptions.TRUE);
// FixCorrectionProposal proposal =
// new FixCorrectionProposal(fix, new Java50CleanUp(options), 15, image, context);
// proposals.add(proposal);
// }
}
public static void addDeprecatedAnnotationProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
//TODO
// IProposableFix fix = Java50Fix.createAddDeprectatedAnnotation(context.getASTRoot(), problem);
// if (fix != null)
// {
// Image image = new Image(JavaClientBundle.INSTANCE.correction_change());
// Map<String, String> options = new HashMap<String, String>();
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS, CleanUpOptions.TRUE);
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS_DEPRECATED, CleanUpOptions.TRUE);
// FixCorrectionProposal proposal =
// new FixCorrectionProposal(fix, new Java50CleanUp(options), 15, image, context);
// proposals.add(proposal);
// }
}
public static void addOverridingDeprecatedMethodProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof MethodDeclaration)) {
return;
}
boolean is50OrHigher = true; //JavaModelUtil.is50OrHigher(cu.getJavaProject());
MethodDeclaration methodDecl = (MethodDeclaration)selectedNode;
AST ast = methodDecl.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
if (is50OrHigher) {
Annotation annot = ast.newMarkerAnnotation();
annot.setTypeName(ast.newName("Deprecated")); //$NON-NLS-1$
rewrite.getListRewrite(methodDecl, methodDecl.getModifiersProperty()).insertFirst(annot, null);
}
Javadoc javadoc = methodDecl.getJavadoc();
if (javadoc != null || !is50OrHigher) {
if (!is50OrHigher) {
javadoc = ast.newJavadoc();
rewrite.set(methodDecl, MethodDeclaration.JAVADOC_PROPERTY, javadoc, null);
}
TagElement newTag = ast.newTagElement();
newTag.setTagName(TagElement.TAG_DEPRECATED);
JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY), newTag, null);
}
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_overrides_deprecated_description();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal =
new ASTRewriteCorrectionProposal(label, rewrite, 15, context.getDocument(), image);
proposals.add(proposal);
}
public static void removeOverrideAnnotationProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) throws CoreException {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof MethodDeclaration)) {
return;
}
MethodDeclaration methodDecl = (MethodDeclaration)selectedNode;
Annotation annot = findAnnotation("java.lang.Override", methodDecl.modifiers()); //$NON-NLS-1$
if (annot != null) {
ASTRewrite rewrite = ASTRewrite.create(annot.getAST());
rewrite.remove(annot, null);
String label = CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_remove_override();
Images image = Images.correction_change;
ASTRewriteCorrectionProposal proposal =
new ASTRewriteCorrectionProposal(label, rewrite, 6, context.getDocument(), image);
proposals.add(proposal);
QuickAssistProcessorImpl.getCreateInSuperClassProposals(context, methodDecl.getName(), proposals);
}
}
public static void addSynchronizedMethodProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
addAddMethodModifierProposal(context, problem, proposals, Modifier.SYNCHRONIZED,
CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_addsynchronized_description());
}
public static void addStaticMethodProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals) {
addAddMethodModifierProposal(context, problem, proposals, Modifier.STATIC,
CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_addstatic_description());
}
private static void addAddMethodModifierProposal(InvocationContext context, IProblemLocation problem,
Collection<ICommandAccess> proposals, int modifier, String label) {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof MethodDeclaration)) {
return;
}
IBinding binding = ((MethodDeclaration)selectedNode).resolveBinding();
if (binding instanceof IMethodBinding) {
binding = ((IMethodBinding)binding).getMethodDeclaration();
Images image = Images.correction_change;
proposals.add(new ModifierChangeCorrectionProposal(label, binding, selectedNode, modifier, 0, 5, context
.getDocument(), image));
}
}
private static final String KEY_MODIFIER = "modifier"; //$NON-NLS-1$
// private static class ModifierLinkedModeProposal extends LinkedProposalPositionGroup.Proposal
// {
//
// private final int fModifier;
//
// public ModifierLinkedModeProposal(int modifier, int relevance)
// {
// super(null, null, relevance);
// fModifier = modifier;
// }
//
// @Override
// public String getAdditionalProposalInfo()
// {
// return getDisplayString();
// }
//
// @Override
// public String getDisplayString()
// {
// if (fModifier == 0)
// {
// return CorrectionMessages.INSTANCE.ModifierCorrectionSubProcessor_default_visibility_label;
// }
// else
// {
// return ModifierKeyword.fromFlagValue(fModifier).toString();
// }
// }
//
// /* (non-Javadoc)
// * @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)
// */
// @Override
// public TextEdit computeEdits(int offset, LinkedPosition currentPosition, char trigger, int stateMask,
// LinkedModeModel model) throws CoreException
// {
// try
// {
// IDocument document = currentPosition.getDocument();
// MultiTextEdit edit = new MultiTextEdit();
// int documentLen = document.getLength();
// if (fModifier == 0)
// {
// int end = currentPosition.offset + currentPosition.length; // current end position
// int k = end;
// while (k < documentLen && IndentManipulation.isIndentChar(document.getChar(k)))
// {
// k++;
// }
// // first remove space then replace range (remove space can destroy empty position)
// edit.addChild(new ReplaceEdit(end, k - end, new String())); // remove extra spaces
// edit.addChild(new ReplaceEdit(currentPosition.offset, currentPosition.length, new String()));
// }
// else
// {
// // first then replace range the insert space (insert space can destroy empty position)
// edit.addChild(new ReplaceEdit(currentPosition.offset, currentPosition.length, ModifierKeyword
// .fromFlagValue(fModifier).toString()));
// int end = currentPosition.offset + currentPosition.length; // current end position
// if (end < documentLen && !Character.isWhitespace(document.getChar(end)))
// {
// edit.addChild(new ReplaceEdit(end, 0, String.valueOf(' '))); // insert extra space
// }
// }
// return edit;
// }
// catch (BadLocationException e)
// {
// throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, e.getMessage(), e));
// }
// }
// }
// public static void installLinkedVisibilityProposals(LinkedProposalModel linkedProposalModel, ASTRewrite rewrite,
// List<IExtendedModifier> modifiers, boolean inInterface)
// {
// ASTNode modifier = findVisibilityModifier(modifiers);
// if (modifier != null)
// {
// int selected = ((Modifier)modifier).getKeyword().toFlagValue();
//
// LinkedProposalPositionGroup positionGroup = linkedProposalModel.getPositionGroup(KEY_MODIFIER, true);
// positionGroup.addPosition(rewrite.track(modifier), false);
// positionGroup.addProposal(new ModifierLinkedModeProposal(selected, 10));
//
// // add all others
// int[] flagValues =
// inInterface ? new int[]{Modifier.PUBLIC, 0} : new int[]{Modifier.PUBLIC, 0, Modifier.PROTECTED,
// Modifier.PRIVATE};
// for (int i = 0; i < flagValues.length; i++)
// {
// if (flagValues[i] != selected)
// {
// positionGroup.addProposal(new ModifierLinkedModeProposal(flagValues[i], 9 - i));
// }
// }
// }
// }
private static Modifier findVisibilityModifier(List<IExtendedModifier> modifiers) {
for (int i = 0; i < modifiers.size(); i++) {
IExtendedModifier curr = modifiers.get(i);
if (curr instanceof Modifier) {
Modifier modifier = (Modifier)curr;
ModifierKeyword keyword = modifier.getKeyword();
if (keyword == ModifierKeyword.PUBLIC_KEYWORD || keyword == ModifierKeyword.PROTECTED_KEYWORD
|| keyword == ModifierKeyword.PRIVATE_KEYWORD) {
return modifier;
}
}
}
return null;
}
private static Annotation findAnnotation(String qualifiedTypeName, List<IExtendedModifier> modifiers) {
for (int i = 0; i < modifiers.size(); i++) {
IExtendedModifier curr = modifiers.get(i);
if (curr instanceof Annotation) {
Annotation annot = (Annotation)curr;
ITypeBinding binding = annot.getTypeName().resolveTypeBinding();
if (binding != null && qualifiedTypeName.equals(binding.getQualifiedName())) {
return annot;
}
}
}
return null;
}
}