| /******************************************************************************* |
| * Copyright (c) 2000, 2012 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.jdt.internal.ui.text.correction.proposals; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.ui.ISharedImages; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTVisitor; |
| import org.eclipse.jdt.core.dom.Assignment; |
| import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.FieldAccess; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.Javadoc; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.NodeFinder; |
| import org.eclipse.jdt.core.dom.PostfixExpression; |
| import org.eclipse.jdt.core.dom.PrefixExpression; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.SuperMethodInvocation; |
| import org.eclipse.jdt.core.dom.TagElement; |
| import org.eclipse.jdt.core.dom.VariableDeclarationExpression; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.SharedASTProvider; |
| import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; |
| import org.eclipse.jdt.internal.ui.text.correction.JavadocTagsSubProcessor; |
| import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; |
| |
| public class RemoveDeclarationCorrectionProposal extends ASTRewriteCorrectionProposal { |
| |
| private static class SideEffectFinder extends ASTVisitor { |
| |
| private ArrayList<Expression> fSideEffectNodes; |
| |
| public SideEffectFinder(ArrayList<Expression> res) { |
| fSideEffectNodes= res; |
| } |
| |
| @Override |
| public boolean visit(Assignment node) { |
| fSideEffectNodes.add(node); |
| return false; |
| } |
| |
| @Override |
| public boolean visit(PostfixExpression node) { |
| fSideEffectNodes.add(node); |
| return false; |
| } |
| |
| @Override |
| public boolean visit(PrefixExpression node) { |
| Object operator= node.getOperator(); |
| if (operator == PrefixExpression.Operator.INCREMENT || operator == PrefixExpression.Operator.DECREMENT) { |
| fSideEffectNodes.add(node); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean visit(MethodInvocation node) { |
| fSideEffectNodes.add(node); |
| return false; |
| } |
| |
| @Override |
| public boolean visit(ClassInstanceCreation node) { |
| fSideEffectNodes.add(node); |
| return false; |
| } |
| |
| @Override |
| public boolean visit(SuperMethodInvocation node) { |
| fSideEffectNodes.add(node); |
| return false; |
| } |
| } |
| |
| |
| private SimpleName fName; |
| |
| public RemoveDeclarationCorrectionProposal(ICompilationUnit cu, SimpleName name, int relevance) { |
| super("", cu, null, relevance, JavaPlugin.getDefault().getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE)); //$NON-NLS-1$ |
| fName= name; |
| } |
| |
| @Override |
| public String getName() { |
| IBinding binding= fName.resolveBinding(); |
| String name= BasicElementLabels.getJavaElementName(fName.getIdentifier()); |
| switch (binding.getKind()) { |
| case IBinding.TYPE: |
| return Messages.format(CorrectionMessages.RemoveDeclarationCorrectionProposal_removeunusedtype_description, name); |
| case IBinding.METHOD: |
| if (((IMethodBinding) binding).isConstructor()) { |
| return Messages.format(CorrectionMessages.RemoveDeclarationCorrectionProposal_removeunusedconstructor_description, name); |
| } else { |
| return Messages.format(CorrectionMessages.RemoveDeclarationCorrectionProposal_removeunusedmethod_description, name); |
| } |
| case IBinding.VARIABLE: |
| if (((IVariableBinding) binding).isField()) { |
| return Messages.format(CorrectionMessages.RemoveDeclarationCorrectionProposal_removeunusedfield_description, name); |
| } else { |
| return Messages.format(CorrectionMessages.RemoveDeclarationCorrectionProposal_removeunusedvar_description, name); |
| } |
| default: |
| return super.getDisplayString(); |
| } |
| } |
| |
| /*(non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite() |
| */ |
| @Override |
| protected ASTRewrite getRewrite() { |
| IBinding binding= fName.resolveBinding(); |
| CompilationUnit root= (CompilationUnit) fName.getRoot(); |
| ASTRewrite rewrite; |
| if (binding.getKind() == IBinding.METHOD) { |
| IMethodBinding decl= ((IMethodBinding) binding).getMethodDeclaration(); |
| ASTNode declaration= root.findDeclaringNode(decl); |
| rewrite= ASTRewrite.create(root.getAST()); |
| rewrite.remove(declaration, null); |
| } else if (binding.getKind() == IBinding.TYPE) { |
| ITypeBinding decl= ((ITypeBinding) binding).getTypeDeclaration(); |
| ASTNode declaration= root.findDeclaringNode(decl); |
| rewrite= ASTRewrite.create(root.getAST()); |
| rewrite.remove(declaration, null); |
| } else if (binding.getKind() == IBinding.VARIABLE) { |
| // needs full AST |
| CompilationUnit completeRoot= SharedASTProvider.getAST(getCompilationUnit(), SharedASTProvider.WAIT_YES, null); |
| |
| SimpleName nameNode= (SimpleName) NodeFinder.perform(completeRoot, fName.getStartPosition(), fName.getLength()); |
| |
| rewrite= ASTRewrite.create(completeRoot.getAST()); |
| SimpleName[] references= LinkedNodeFinder.findByBinding(completeRoot, nameNode.resolveBinding()); |
| for (int i= 0; i < references.length; i++) { |
| removeVariableReferences(rewrite, references[i]); |
| } |
| |
| IVariableBinding bindingDecl= ((IVariableBinding) nameNode.resolveBinding()).getVariableDeclaration(); |
| ASTNode declaringNode= completeRoot.findDeclaringNode(bindingDecl); |
| if (declaringNode instanceof SingleVariableDeclaration) { |
| removeParamTag(rewrite, (SingleVariableDeclaration) declaringNode); |
| } |
| } else { |
| throw new IllegalArgumentException("Unexpected binding"); //$NON-NLS-1$ |
| } |
| return rewrite; |
| } |
| |
| private void removeParamTag(ASTRewrite rewrite, SingleVariableDeclaration varDecl) { |
| if (varDecl.getParent() instanceof MethodDeclaration) { |
| Javadoc javadoc= ((MethodDeclaration) varDecl.getParent()).getJavadoc(); |
| if (javadoc != null) { |
| TagElement tagElement= JavadocTagsSubProcessor.findParamTag(javadoc, varDecl.getName().getIdentifier()); |
| if (tagElement != null) { |
| rewrite.remove(tagElement, null); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Remove the field or variable declaration including the initializer. |
| * @param rewrite the ast rewrite |
| * @param reference the reference |
| */ |
| private void removeVariableReferences(ASTRewrite rewrite, SimpleName reference) { |
| ASTNode parent= reference.getParent(); |
| while (parent instanceof QualifiedName) { |
| parent= parent.getParent(); |
| } |
| if (parent instanceof FieldAccess) { |
| parent= parent.getParent(); |
| } |
| |
| int nameParentType= parent.getNodeType(); |
| if (nameParentType == ASTNode.ASSIGNMENT) { |
| Assignment assignment= (Assignment) parent; |
| Expression rightHand= assignment.getRightHandSide(); |
| |
| ASTNode assignParent= assignment.getParent(); |
| if (assignParent.getNodeType() == ASTNode.EXPRESSION_STATEMENT && rightHand.getNodeType() != ASTNode.ASSIGNMENT) { |
| removeVariableWithInitializer(rewrite, rightHand, assignParent); |
| } else { |
| rewrite.replace(assignment, rewrite.createCopyTarget(rightHand), null); |
| } |
| } else if (nameParentType == ASTNode.SINGLE_VARIABLE_DECLARATION) { |
| rewrite.remove(parent, null); |
| } else if (nameParentType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) { |
| VariableDeclarationFragment frag= (VariableDeclarationFragment) parent; |
| ASTNode varDecl= frag.getParent(); |
| List<VariableDeclarationFragment> fragments; |
| if (varDecl instanceof VariableDeclarationExpression) { |
| fragments= ((VariableDeclarationExpression) varDecl).fragments(); |
| } else if (varDecl instanceof FieldDeclaration) { |
| fragments= ((FieldDeclaration) varDecl).fragments(); |
| } else { |
| fragments= ((VariableDeclarationStatement) varDecl).fragments(); |
| } |
| if (fragments.size() == 1) { |
| rewrite.remove(varDecl, null); |
| } else { |
| rewrite.remove(frag, null); // don't try to preserve |
| } |
| } |
| } |
| |
| private void removeVariableWithInitializer(ASTRewrite rewrite, ASTNode initializerNode, ASTNode statementNode) { |
| ArrayList<Expression> sideEffectNodes= new ArrayList<Expression>(); |
| initializerNode.accept(new SideEffectFinder(sideEffectNodes)); |
| int nSideEffects= sideEffectNodes.size(); |
| if (nSideEffects == 0) { |
| if (ASTNodes.isControlStatementBody(statementNode.getLocationInParent())) { |
| rewrite.replace(statementNode, rewrite.getAST().newBlock(), null); |
| } else { |
| rewrite.remove(statementNode, null); |
| } |
| } else { |
| // do nothing yet |
| } |
| } |
| |
| } |