blob: af2b69614a59cc23782b30666dfab5a57bdff40b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.text.correction;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.jsdt.core.Flags;
import org.eclipse.wst.jsdt.core.IField;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.compiler.IProblem;
import org.eclipse.wst.jsdt.core.dom.AST;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.Assignment;
import org.eclipse.wst.jsdt.core.dom.Block;
import org.eclipse.wst.jsdt.core.dom.CastExpression;
import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation;
import org.eclipse.wst.jsdt.core.dom.Expression;
import org.eclipse.wst.jsdt.core.dom.FieldAccess;
import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration;
import org.eclipse.wst.jsdt.core.dom.FunctionInvocation;
import org.eclipse.wst.jsdt.core.dom.IBinding;
import org.eclipse.wst.jsdt.core.dom.IFunctionBinding;
import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
import org.eclipse.wst.jsdt.core.dom.IVariableBinding;
import org.eclipse.wst.jsdt.core.dom.InfixExpression;
import org.eclipse.wst.jsdt.core.dom.JSdoc;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.Modifier;
import org.eclipse.wst.jsdt.core.dom.Name;
import org.eclipse.wst.jsdt.core.dom.NumberLiteral;
import org.eclipse.wst.jsdt.core.dom.ParenthesizedExpression;
import org.eclipse.wst.jsdt.core.dom.PostfixExpression;
import org.eclipse.wst.jsdt.core.dom.PrefixExpression;
import org.eclipse.wst.jsdt.core.dom.PrimitiveType;
import org.eclipse.wst.jsdt.core.dom.QualifiedName;
import org.eclipse.wst.jsdt.core.dom.ReturnStatement;
import org.eclipse.wst.jsdt.core.dom.SimpleName;
import org.eclipse.wst.jsdt.core.dom.SimpleType;
import org.eclipse.wst.jsdt.core.dom.SuperConstructorInvocation;
import org.eclipse.wst.jsdt.core.dom.SuperFieldAccess;
import org.eclipse.wst.jsdt.core.dom.SuperMethodInvocation;
import org.eclipse.wst.jsdt.core.dom.TagElement;
import org.eclipse.wst.jsdt.core.dom.Type;
import org.eclipse.wst.jsdt.core.dom.TypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.Assignment.Operator;
import org.eclipse.wst.jsdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.wst.jsdt.core.formatter.IndentManipulation;
import org.eclipse.wst.jsdt.internal.corext.codemanipulation.GetterSetterUtil;
import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
import org.eclipse.wst.jsdt.internal.corext.dom.Bindings;
import org.eclipse.wst.jsdt.internal.corext.fix.LinkedProposalModel;
import org.eclipse.wst.jsdt.internal.corext.fix.LinkedProposalPositionGroup;
import org.eclipse.wst.jsdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.wst.jsdt.internal.corext.refactoring.sef.SelfEncapsulateFieldRefactoring;
import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
import org.eclipse.wst.jsdt.internal.corext.util.JdtFlags;
import org.eclipse.wst.jsdt.internal.corext.util.Messages;
import org.eclipse.wst.jsdt.internal.ui.JavaPluginImages;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.refactoring.RefactoringExecutionHelper;
import org.eclipse.wst.jsdt.internal.ui.refactoring.RefactoringSaveHelper;
import org.eclipse.wst.jsdt.internal.ui.refactoring.actions.RefactoringStarter;
import org.eclipse.wst.jsdt.internal.ui.refactoring.sef.SelfEncapsulateFieldWizard;
import org.eclipse.wst.jsdt.internal.ui.util.ExceptionHandler;
import org.eclipse.wst.jsdt.ui.JavaScriptUI;
import org.eclipse.wst.jsdt.ui.text.java.IInvocationContext;
import org.eclipse.wst.jsdt.ui.text.java.IProblemLocation;
/**
*/
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(IInvocationContext context, IProblemLocation problem, Collection proposals, int kind, int relevance) throws CoreException {
IJavaScriptUnit cu= context.getCompilationUnit();
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.FUNCTION_INVOCATION:
binding= ((FunctionInvocation) 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 IFunctionBinding) {
IFunctionBinding methodDecl= (IFunctionBinding) binding;
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= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changevisibility_description, new String[] { name, getVisibilityString(includedModifiers) });
break;
case TO_STATIC:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertostatic_description, name);
includedModifiers= Modifier.STATIC;
break;
case TO_NON_STATIC:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertononstatic_description, name);
excludedModifiers= Modifier.STATIC;
break;
case TO_NON_PRIVATE:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertodefault_description, name);
excludedModifiers= Modifier.PRIVATE;
break;
case TO_NON_FINAL:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertononfinal_description, name);
excludedModifiers= Modifier.FINAL;
break;
default:
throw new IllegalArgumentException("not supported"); //$NON-NLS-1$
}
IJavaScriptUnit targetCU= isLocalVar ? cu : ASTResolving.findCompilationUnitForBinding(cu, context.getASTRoot(), typeBinding.getTypeDeclaration());
if (targetCU != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
proposals.add(new ModifierChangeCompletionProposal(label, targetCU, bindingDecl, selectedNode, includedModifiers, excludedModifiers, relevance, image));
}
}
if (kind == TO_VISIBLE && bindingDecl.getKind() == IBinding.VARIABLE) {
UnresolvedElementsSubProcessor.getVariableProposals(context, problem, (IVariableBinding) bindingDecl, proposals);
}
}
public static void addChangeOverriddenModfierProposal(IInvocationContext context, IProblemLocation problem, Collection proposals, int kind) throws JavaScriptModelException {
IJavaScriptUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof FunctionDeclaration)) {
return;
}
IFunctionBinding method= ((FunctionDeclaration) selectedNode).resolveBinding();
ITypeBinding curr= method.getDeclaringClass();
if (kind == TO_VISIBLE && problem.getProblemId() != IProblem.OverridingNonVisibleMethod) {
IFunctionBinding defining= Bindings.findOverriddenMethod(method, false);
if (defining != null) {
int excludedModifiers= Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
int includedModifiers= JdtFlags.getVisibilityCode(defining);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemethodvisibility_description, new String[] { getVisibilityString(includedModifiers) });
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
proposals.add(new ModifierChangeCompletionProposal(label, cu, method, selectedNode, includedModifiers, excludedModifiers, 8, image));
}
}
IFunctionBinding overriddenInClass= null;
while (overriddenInClass == null && curr.getSuperclass() != null) {
curr= curr.getSuperclass();
overriddenInClass= Bindings.findOverriddenMethodInType(curr, method);
}
if (overriddenInClass != null) {
IFunctionBinding overriddenDecl= overriddenInClass.getMethodDeclaration();
IJavaScriptUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, context.getASTRoot(), overriddenDecl.getDeclaringClass());
if (targetCU != null) {
String methodName= 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= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changeoverriddenvisibility_description, new String[] { methodName, getVisibilityString(includedModifiers) });
break;
case TO_NON_FINAL:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononfinal_description, methodName);
excludedModifiers= Modifier.FINAL;
includedModifiers= 0;
break;
case TO_NON_STATIC:
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononstatic_description, methodName);
excludedModifiers= Modifier.STATIC;
includedModifiers= 0;
break;
default:
Assert.isTrue(false, "not supported"); //$NON-NLS-1$
return;
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
proposals.add(new ModifierChangeCompletionProposal(label, targetCU, overriddenDecl, selectedNode, includedModifiers, excludedModifiers, 7, image));
}
}
}
public static void addNonFinalLocalProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) {
IJavaScriptUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof SimpleName)) {
return;
}
IBinding binding= ((SimpleName) selectedNode).resolveBinding();
if (binding instanceof IVariableBinding) {
binding= ((IVariableBinding) binding).getVariableDeclaration();
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertofinal_description, binding.getName());
proposals.add(new ModifierChangeCompletionProposal(label, cu, binding, selectedNode, Modifier.FINAL, 0, 5, image));
}
}
public static void addRemoveInvalidModfiersProposal(IInvocationContext context, IProblemLocation problem, Collection proposals, int relevance) {
IJavaScriptUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof FunctionDeclaration) {
selectedNode= ((FunctionDeclaration) 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= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemethodtononstatic_description, methodName);
break;
case IProblem.UnexpectedStaticModifierForField:
excludedModifiers= Modifier.STATIC;
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changefieldmodifiertononstatic_description, methodName);
break;
case IProblem.IllegalModifierCombinationFinalVolatileForField:
excludedModifiers= Modifier.VOLATILE;
label= CorrectionMessages.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.ABSTRACT | 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);
if (((IFunctionBinding) binding).isConstructor()) {
excludedModifiers |= Modifier.STATIC;
}
break;
case IProblem.IllegalModifierForVariable:
excludedModifiers= ~Modifier.FINAL;
break;
default:
Assert.isTrue(false, "not supported"); //$NON-NLS-1$
return;
}
if (label == null)
label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_removeinvalidmodifiers_description, methodName);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
proposals.add(new ModifierChangeCompletionProposal(label, cu, binding, selectedNode, includedModifiers, excludedModifiers, relevance, image));
if (problemId == IProblem.IllegalModifierCombinationFinalVolatileForField) {
proposals.add(new ModifierChangeCompletionProposal(CorrectionMessages.ModifierCorrectionSubProcessor_removefinal_description, cu, binding, selectedNode, 0, Modifier.FINAL, relevance + 1, image));
}
if (problemId == IProblem.UnexpectedStaticModifierForField && binding instanceof IVariableBinding) {
ITypeBinding declClass= ((IVariableBinding) binding).getDeclaringClass();
if (declClass.isMember()) {
proposals.add(new ModifierChangeCompletionProposal(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertostaticfinal_description, cu, binding, selectedNode, Modifier.FINAL, Modifier.VOLATILE, relevance + 1, image));
ASTNode parentType= context.getASTRoot().findDeclaringNode(declClass);
if (parentType != null) {
proposals.add(new ModifierChangeCompletionProposal(CorrectionMessages.ModifierCorrectionSubProcessor_addstatictoparenttype_description, cu, declClass, parentType, Modifier.STATIC, 0, relevance - 1, image));
}
}
}
if (problemId == IProblem.UnexpectedStaticModifierForMethod && binding instanceof IFunctionBinding) {
ITypeBinding declClass= ((IFunctionBinding) binding).getDeclaringClass();
if (declClass.isMember()) {
ASTNode parentType= context.getASTRoot().findDeclaringNode(declClass);
if (parentType != null) {
proposals.add(new ModifierChangeCompletionProposal(CorrectionMessages.ModifierCorrectionSubProcessor_addstatictoparenttype_description, cu, declClass, parentType, Modifier.STATIC, 0, relevance - 1, 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.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(IInvocationContext context, IProblemLocation problem, Collection proposals) {
IJavaScriptUnit cu= context.getCompilationUnit();
JavaScriptUnit astRoot= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
FunctionDeclaration decl;
if (selectedNode instanceof SimpleName) {
decl= (FunctionDeclaration) selectedNode.getParent();
} else if (selectedNode instanceof FunctionDeclaration) {
decl= (FunctionDeclaration) 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);
if (problem.getProblemId() == IProblem.AbstractMethodInAbstractClass || 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, FunctionDeclaration.BODY_PROPERTY, newBody, null);
Expression expr= ASTNodeFactory.newDefaultExpression(ast, decl.getReturnType2(), decl.getExtraDimensions());
if (expr != null) {
ReturnStatement returnStatement= ast.newReturnStatement();
returnStatement.setExpression(expr);
newBody.statements().add(returnStatement);
}
}
String label= CorrectionMessages.ModifierCorrectionSubProcessor_removeabstract_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 6, image);
proposals.add(proposal);
}
if (!hasNoBody && problem.getProblemId() == IProblem.BodyForAbstractMethod) {
ASTRewrite rewrite= ASTRewrite.create(decl.getAST());
rewrite.remove(decl.getBody(), null);
String label= CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal2= new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image);
proposals.add(proposal2);
}
if (problem.getProblemId() == IProblem.AbstractMethodInAbstractClass && (parentTypeDecl != null)) {
ASTRewriteCorrectionProposal proposal= getMakeTypeAbstractProposal(cu, parentTypeDecl, 5);
proposals.add(proposal);
}
}
public static void addNativeMethodProposals(IInvocationContext context, IProblemLocation problem, Collection proposals) {
IJavaScriptUnit cu= context.getCompilationUnit();
JavaScriptUnit astRoot= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
FunctionDeclaration decl;
if (selectedNode instanceof SimpleName) {
decl= (FunctionDeclaration) selectedNode.getParent();
} else if (selectedNode instanceof FunctionDeclaration) {
decl= (FunctionDeclaration) 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, FunctionDeclaration.BODY_PROPERTY, newBody, null);
Expression expr= ASTNodeFactory.newDefaultExpression(ast, decl.getReturnType2(), decl.getExtraDimensions());
if (expr != null) {
ReturnStatement returnStatement= ast.newReturnStatement();
returnStatement.setExpression(expr);
newBody.statements().add(returnStatement);
}
String label= CorrectionMessages.ModifierCorrectionSubProcessor_removenative_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 6, image);
proposals.add(proposal);
}
if (decl.getBody() != null) {
ASTRewrite rewrite= ASTRewrite.create(decl.getAST());
rewrite.remove(decl.getBody(), null);
String label= CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal2= new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image);
proposals.add(proposal2);
}
}
public static ASTRewriteCorrectionProposal getMakeTypeAbstractProposal(IJavaScriptUnit cu, TypeDeclaration typeDeclaration, int relevance) {
AST ast= typeDeclaration.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
Modifier newModifier= ast.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
rewrite.getListRewrite(typeDeclaration, TypeDeclaration.MODIFIERS2_PROPERTY).insertLast(newModifier, null);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_addabstract_description, typeDeclaration.getName().getIdentifier());
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, relevance, image);
proposal.addLinkedPosition(rewrite.track(newModifier), true, "modifier"); //$NON-NLS-1$
return proposal;
}
public static void addMethodRequiresBodyProposals(IInvocationContext context, IProblemLocation problem, Collection proposals) {
IJavaScriptUnit cu= context.getCompilationUnit();
AST ast= context.getASTRoot().getAST();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof FunctionDeclaration)) {
return;
}
FunctionDeclaration decl= (FunctionDeclaration) selectedNode;
{
ASTRewrite rewrite= ASTRewrite.create(ast);
Modifier modifierNode= ASTNodes.findModifierNode(Modifier.ABSTRACT, decl.modifiers());
if (modifierNode != null) {
rewrite.remove(modifierNode, null);
}
Block body= ast.newBlock();
rewrite.set(decl, FunctionDeclaration.BODY_PROPERTY, body, null);
if (!decl.isConstructor()) {
Type returnType= decl.getReturnType2();
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.ModifierCorrectionSubProcessor_addmissingbody_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 9, image);
proposals.add(proposal);
}
{
ASTRewrite rewrite= ASTRewrite.create(ast);
Modifier newModifier= ast.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
rewrite.getListRewrite(decl, FunctionDeclaration.MODIFIERS2_PROPERTY).insertLast(newModifier, null);
String label= CorrectionMessages.ModifierCorrectionSubProcessor_setmethodabstract_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 8, image);
proposal.addLinkedPosition(rewrite.track(newModifier), true, "modifier"); //$NON-NLS-1$
proposals.add(proposal);
}
}
public static void addNeedToEmulateProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) {
IJavaScriptUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof SimpleName)) {
return;
}
IBinding binding= ((SimpleName) selectedNode).resolveBinding();
if (binding instanceof IVariableBinding) {
binding= ((IVariableBinding) binding).getVariableDeclaration();
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertofinal_description, binding.getName());
proposals.add(new ModifierChangeCompletionProposal(label, cu, binding, selectedNode, Modifier.FINAL, 0, 5, image));
}
}
//
// public static void addOverrideAnnotationProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) throws CoreException {
// IFix fix= Java50Fix.createAddOverrideAnnotationFix(context.getASTRoot(), problem);
// if (fix != null) {
// Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
// Map options= new Hashtable();
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS, CleanUpConstants.TRUE);
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE, CleanUpConstants.TRUE);
// FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new Java50CleanUp(options), 5, image, context);
// proposals.add(proposal);
// }
// }
//
// public static void addDeprecatedAnnotationProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) throws CoreException {
// IFix fix= Java50Fix.createAddDeprectatedAnnotation(context.getASTRoot(), problem);
// if (fix != null) {
// Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
// Map options= new Hashtable();
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS, CleanUpConstants.TRUE);
// options.put(CleanUpConstants.ADD_MISSING_ANNOTATIONS_DEPRECATED, CleanUpConstants.TRUE);
// FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new Java50CleanUp(options), 5, image, context);
// proposals.add(proposal);
// }
// }
public static void addOverridingDeprecatedMethodProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) throws CoreException {
IJavaScriptUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof FunctionDeclaration)) {
return;
}
boolean is50OrHigher= JavaModelUtil.is50OrHigher(cu.getJavaScriptProject());
FunctionDeclaration methodDecl= (FunctionDeclaration) selectedNode;
AST ast= methodDecl.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
JSdoc javadoc= methodDecl.getJavadoc();
if (javadoc != null || !is50OrHigher) {
if (!is50OrHigher) {
javadoc= ast.newJSdoc();
rewrite.set(methodDecl, FunctionDeclaration.JAVADOC_PROPERTY, javadoc, null);
}
TagElement newTag= ast.newTagElement();
newTag.setTagName(TagElement.TAG_DEPRECATED);
JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, JSdoc.TAGS_PROPERTY), newTag, null);
}
String label= CorrectionMessages.ModifierCorrectionSubProcessor_overrides_deprecated_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 15, image);
proposals.add(proposal);
}
public static void removeOverrideAnnotationProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) throws CoreException {
// IJavaScriptUnit cu= context.getCompilationUnit();
//
// ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
// if (!(selectedNode instanceof FunctionDeclaration)) {
// return;
// }
// FunctionDeclaration methodDecl= (FunctionDeclaration) 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.ModifierCorrectionSubProcessor_remove_override;
// Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
// ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 6, image);
// proposals.add(proposal);
//
// QuickAssistProcessor.getCreateInSuperClassProposals(context, methodDecl.getName(), proposals);
// }
}
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;
}
public String getAdditionalProposalInfo() {
return getDisplayString();
}
public String getDisplayString() {
if (fModifier == 0) {
return CorrectionMessages.ModifierCorrectionSubProcessor_default_visibility_label;
} else {
return ModifierKeyword.fromFlagValue(fModifier).toString();
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.internal.corext.fix.PositionGroup.Proposal#computeEdits(int, org.eclipse.jface.text.link.LinkedPosition, char, int, org.eclipse.jface.text.link.LinkedModeModel)
*/
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, JavaScriptUI.ID_PLUGIN, IStatus.ERROR, e.getMessage(), e));
}
}
}
public static void installLinkedVisibilityProposals(LinkedProposalModel linkedProposalModel, ASTRewrite rewrite, List 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 modifiers) {
for (int i= 0; i < modifiers.size(); i++) {
Object 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 class ProposalParameter {
public final boolean useSuper;
public final IJavaScriptUnit compilationUnit;
public final ASTRewrite astRewrite;
public final Expression accessNode;
public final Expression qualifier;
public final IVariableBinding variableBinding;
public ProposalParameter(boolean useSuper, IJavaScriptUnit compilationUnit, ASTRewrite rewrite, Expression accessNode, Expression qualifier, IVariableBinding variableBinding) {
this.useSuper= useSuper;
this.compilationUnit= compilationUnit;
this.astRewrite= rewrite;
this.accessNode= accessNode;
this.qualifier= qualifier;
this.variableBinding= variableBinding;
}
}
public static class SelfEncapsulateFieldProposal extends ChangeCorrectionProposal {
private IField fField;
private boolean fNoDialog;
public SelfEncapsulateFieldProposal(int relevance, IField field, boolean isReadAccess) {
super(getDescription(isReadAccess), null, relevance, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));
fField= field;
fNoDialog= false;
}
public void setNoDialog(boolean noDialog) {
fNoDialog= noDialog;
}
private static String getDescription(boolean getter) {
if (getter)
return CorrectionMessages.ModifierCorrectionSubProcessor_creategetterunsingencapsulatefield_description;
else
return CorrectionMessages.ModifierCorrectionSubProcessor_createsetterusingencapsulatefield_description;
}
public void apply(IDocument document) {
try {
final SelfEncapsulateFieldRefactoring refactoring= new SelfEncapsulateFieldRefactoring(fField);
refactoring.setVisibility(Flags.AccPublic);
refactoring.setConsiderVisibility(false);//private field references are just searched in local file
if (fNoDialog) {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
final RefactoringExecutionHelper helper= new RefactoringExecutionHelper(refactoring, RefactoringStatus.ERROR, RefactoringSaveHelper.SAVE_JAVA_ONLY_UPDATES, JavaScriptPlugin.getActiveWorkbenchShell(), window);
if (Display.getCurrent() != null) {
try {
helper.perform(false, false);
} catch (InterruptedException e) {
JavaScriptPlugin.log(e);
} catch (InvocationTargetException e) {
JavaScriptPlugin.log(e);
}
} else {
Display.getDefault().syncExec(new Runnable() {
public void run() {
try {
helper.perform(false, false);
} catch (InterruptedException e) {
JavaScriptPlugin.log(e);
} catch (InvocationTargetException e) {
JavaScriptPlugin.log(e);
}
}
});
}
} else {
new RefactoringStarter().activate(refactoring, new SelfEncapsulateFieldWizard(refactoring), JavaScriptPlugin.getActiveWorkbenchShell(), "", RefactoringSaveHelper.SAVE_JAVA_ONLY_UPDATES); //$NON-NLS-1$
}
} catch (JavaScriptModelException e) {
ExceptionHandler.handle(e, CorrectionMessages.ModifierCorrectionSubProcessor_encapsulate_field_error_title, CorrectionMessages.ModifierCorrectionSubProcessor_encapsulate_field_error_message);
}
}
}
public static void addGetterSetterProposal(IInvocationContext context, IProblemLocation problem, Collection proposals, int relevance) {
ASTNode coveringNode= problem.getCoveringNode(context.getASTRoot());
IJavaScriptUnit compilationUnit= context.getCompilationUnit();
if (coveringNode instanceof SimpleName) {
SimpleName sn= (SimpleName) coveringNode;
if (sn.isDeclaration())
return;
IVariableBinding variableBinding= (IVariableBinding) sn.resolveBinding();
if (variableBinding == null || !variableBinding.isField())
return;
ChangeCorrectionProposal proposal= getProposal(compilationUnit, sn, variableBinding, relevance);
if (proposal != null)
proposals.add(proposal);
}
}
private static ChangeCorrectionProposal getProposal(IJavaScriptUnit cu, SimpleName sn, IVariableBinding variableBinding, int relevance) {
Expression accessNode= sn;
Expression qualifier= null;
AST ast= sn.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
boolean useSuper= false;
boolean writeAccess= ASTResolving.isWriteAccess(sn);
ASTNode parent= sn.getParent();
switch (parent.getNodeType()) {
case ASTNode.QUALIFIED_NAME:
accessNode= (Expression) parent;
qualifier= ((QualifiedName) parent).getQualifier();
break;
case ASTNode.SUPER_FIELD_ACCESS:
accessNode= (Expression) parent;
qualifier= ((SuperFieldAccess) parent).getQualifier();
useSuper= true;
break;
}
ProposalParameter gspc= new ProposalParameter(useSuper, cu, rewrite, accessNode, qualifier, variableBinding);
if (writeAccess)
return addSetterProposal(gspc, relevance);
else
return addGetterProposal(gspc, relevance);
}
/**
* Proposes a getter for this field
* @param context
* @param relevance relevance of this proposal
* @return the proposal if available or null
*/
private static ChangeCorrectionProposal addGetterProposal(ProposalParameter context, int relevance) {
IFunctionBinding method= findGetter(context);
if (method != null) {
Expression mi= createMethodInvocation(context, method, null);
context.astRewrite.replace(context.accessNode, mi, null);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_replacewithgetter_description, context.accessNode);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.compilationUnit, context.astRewrite, relevance, image);
return proposal;
} else {
IJavaScriptElement element= context.variableBinding.getJavaElement();
if (element instanceof IField) {
IField field= (IField) element;
try {
if (RefactoringAvailabilityTester.isSelfEncapsulateAvailable(field))
return new SelfEncapsulateFieldProposal(relevance, field, true);
} catch (JavaScriptModelException e) {
JavaScriptPlugin.log(e);
}
}
}
return null;
}
private static IFunctionBinding findGetter(ProposalParameter context) {
ITypeBinding returnType= context.variableBinding.getType();
String getterName= GetterSetterUtil.getGetterName(context.variableBinding, context.compilationUnit.getJavaScriptProject(), null, isBoolean(context));
ITypeBinding declaringType= context.variableBinding.getDeclaringClass();
IFunctionBinding getter= Bindings.findMethodInHierarchy(declaringType, getterName, new ITypeBinding[0]);
if (getter != null && getter.getReturnType().isAssignmentCompatible(returnType) && Modifier.isStatic(getter.getModifiers()) == Modifier.isStatic(context.variableBinding.getModifiers()))
return getter;
return null;
}
private static Expression createMethodInvocation(ProposalParameter context, IFunctionBinding method, Expression argument) {
AST ast= context.astRewrite.getAST();
Expression qualifier= context.qualifier;
if (context.useSuper) {
SuperMethodInvocation invocation= ast.newSuperMethodInvocation();
invocation.setName(ast.newSimpleName(method.getName()));
if (qualifier != null)
invocation.setQualifier((Name) context.astRewrite.createCopyTarget(qualifier));
if (argument != null)
invocation.arguments().add(argument);
return invocation;
} else {
FunctionInvocation invocation= ast.newFunctionInvocation();
invocation.setName(ast.newSimpleName(method.getName()));
if (qualifier != null)
invocation.setExpression((Expression) context.astRewrite.createCopyTarget(qualifier));
if (argument != null)
invocation.arguments().add(argument);
return invocation;
}
}
/**
* Proposes a setter for this field
* @param context
* @param relevance relevance of this proposal
* @return the proposal if available or null
*/
private static ChangeCorrectionProposal addSetterProposal(ProposalParameter context, int relevance) {
boolean isBoolean= isBoolean(context);
String setterName= GetterSetterUtil.getSetterName(context.variableBinding, context.compilationUnit.getJavaScriptProject(), null, isBoolean);
ITypeBinding declaringType= context.variableBinding.getDeclaringClass();
IFunctionBinding method= Bindings.findMethodInHierarchy(declaringType, setterName, new ITypeBinding[] { context.variableBinding.getType() });
if (method != null && Bindings.isVoidType(method.getReturnType()) && (Modifier.isStatic(method.getModifiers()) == Modifier.isStatic(context.variableBinding.getModifiers()))) {
Expression assignedValue= getAssignedValue(context);
if (assignedValue == null)
return null; //we don't know how to handle those cases.
Expression mi= createMethodInvocation(context, method, assignedValue);
context.astRewrite.replace(context.accessNode.getParent(), mi, null);
String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_replacewithsetter_description, context.accessNode);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.compilationUnit, context.astRewrite, relevance, image);
return proposal;
} else {
IJavaScriptElement element= context.variableBinding.getJavaElement();
if (element instanceof IField) {
IField field= (IField) element;
try {
if (RefactoringAvailabilityTester.isSelfEncapsulateAvailable(field))
return new SelfEncapsulateFieldProposal(relevance, field, false);
} catch (JavaScriptModelException e) {
JavaScriptPlugin.log(e);
}
}
}
return null;
}
private static boolean isBoolean(ProposalParameter context) {
AST ast= context.astRewrite.getAST();
boolean isBoolean= ast.resolveWellKnownType("boolean") == context.variableBinding.getType(); //$NON-NLS-1$
if (!isBoolean)
isBoolean= ast.resolveWellKnownType("java.lang.Boolean") == context.variableBinding.getType(); //$NON-NLS-1$
return isBoolean;
}
private static Expression getAssignedValue(ProposalParameter context) {
ASTNode parent= context.accessNode.getParent();
AST ast= context.astRewrite.getAST();
switch (parent.getNodeType()) {
case ASTNode.ASSIGNMENT:
Assignment assignment= ((Assignment) parent);
Expression rightHandSide= assignment.getRightHandSide();
Expression copiedRightOp= (Expression) context.astRewrite.createCopyTarget(rightHandSide);
if (isNotInBlock(parent))
break;
if (assignment.getOperator() == Operator.ASSIGN) {
ITypeBinding rightHandSideType= rightHandSide.resolveTypeBinding();
copiedRightOp= checkForNarrowCast(context, copiedRightOp, true, rightHandSideType);
return copiedRightOp;
}
IFunctionBinding getter= findGetter(context);
if (getter != null) {
InfixExpression infix= ast.newInfixExpression();
infix.setLeftOperand(createMethodInvocation(context, getter, null));
infix.setOperator(ASTNodes.convertToInfixOperator(assignment.getOperator()));
infix.setRightOperand(copiedRightOp);
ITypeBinding infixType= infix.resolveTypeBinding();
return checkForNarrowCast(context, infix, true, infixType);
}
break;
case ASTNode.POSTFIX_EXPRESSION:
PostfixExpression po= (PostfixExpression) parent;
if (isNotInBlock(parent))
break;
InfixExpression.Operator postfixOp= null;
if (po.getOperator() == PostfixExpression.Operator.INCREMENT)
postfixOp= InfixExpression.Operator.PLUS;
if (po.getOperator() == PostfixExpression.Operator.DECREMENT)
postfixOp= InfixExpression.Operator.MINUS;
if (postfixOp == null)
break;
return createInfixInvocationFromPostPrefixExpression(context, postfixOp);
case ASTNode.PREFIX_EXPRESSION:
PrefixExpression pe= (PrefixExpression) parent;
if (isNotInBlock(parent))
break;
InfixExpression.Operator prefixOp= null;
if (pe.getOperator() == PrefixExpression.Operator.INCREMENT)
prefixOp= InfixExpression.Operator.PLUS;
if (pe.getOperator() == PrefixExpression.Operator.DECREMENT)
prefixOp= InfixExpression.Operator.MINUS;
if (prefixOp == null)
break;
return createInfixInvocationFromPostPrefixExpression(context, prefixOp);
}
return null;
}
private static boolean isNotInBlock(ASTNode parent) {
ASTNode grandParent= parent.getParent();
return (grandParent.getNodeType() != ASTNode.EXPRESSION_STATEMENT) || (grandParent.getParent().getNodeType() != ASTNode.BLOCK);
}
private static Expression createInfixInvocationFromPostPrefixExpression(ProposalParameter context, InfixExpression.Operator operator) {
AST ast= context.astRewrite.getAST();
IFunctionBinding getter= findGetter(context);
if (getter != null) {
InfixExpression infix= ast.newInfixExpression();
infix.setLeftOperand(createMethodInvocation(context, getter, null));
infix.setOperator(operator);
NumberLiteral number= ast.newNumberLiteral();
number.setToken("1"); //$NON-NLS-1$
infix.setRightOperand(number);
ITypeBinding infixType= infix.resolveTypeBinding();
return checkForNarrowCast(context, infix, true, infixType);
}
return null;
}
/**
*
* @param context general context
* @param expression the right handside
* @param parenthesize if true places () around expression
* @param expressionType the type of the right handside. Can be null
* @return the casted expression if necessary
*/
private static Expression checkForNarrowCast(ProposalParameter context, Expression expression, boolean parenthesize, ITypeBinding expressionType) {
PrimitiveType castTo= null;
ITypeBinding type= context.variableBinding.getType();
if (type.isEqualTo(expressionType))
return expression; //no cast for same type
AST ast= context.astRewrite.getAST();
if (JavaModelUtil.is50OrHigher(context.compilationUnit.getJavaScriptProject())) {
if (ast.resolveWellKnownType("java.lang.Character").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.CHAR);
if (ast.resolveWellKnownType("java.lang.Byte").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.BYTE);
if (ast.resolveWellKnownType("java.lang.Short").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.SHORT);
}
if (ast.resolveWellKnownType("char").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.CHAR);
if (ast.resolveWellKnownType("byte").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.BYTE);
if (ast.resolveWellKnownType("short").isEqualTo(type)) //$NON-NLS-1$
castTo= ast.newPrimitiveType(PrimitiveType.SHORT);
if (castTo != null) {
CastExpression cast= ast.newCastExpression();
if (parenthesize) {
ParenthesizedExpression parenthesized= ast.newParenthesizedExpression();
parenthesized.setExpression(expression);
cast.setExpression(parenthesized);
} else
cast.setExpression(expression);
cast.setType(castTo);
return cast;
}
return expression;
}
}