| /******************************************************************************* |
| * Copyright (c) 2004 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.jst.jsp.ui.internal.correction; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
| import org.eclipse.jdt.core.dom.Assignment; |
| import org.eclipse.jdt.core.dom.Block; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.CastExpression; |
| import org.eclipse.jdt.core.dom.CatchClause; |
| import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; |
| import org.eclipse.jdt.core.dom.ConditionalExpression; |
| import org.eclipse.jdt.core.dom.DoStatement; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.ExpressionStatement; |
| import org.eclipse.jdt.core.dom.ForStatement; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.IfStatement; |
| import org.eclipse.jdt.core.dom.InfixExpression; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.ParenthesizedExpression; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SimpleType; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.Statement; |
| import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
| import org.eclipse.jdt.core.dom.ThisExpression; |
| import org.eclipse.jdt.core.dom.TryStatement; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| 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.WhileStatement; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; |
| import org.eclipse.jdt.internal.corext.dom.NodeFinder; |
| import org.eclipse.jdt.internal.ui.JavaPluginImages; |
| import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; |
| import org.eclipse.jdt.internal.ui.text.correction.AssignToVariableAssistProposal; |
| import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; |
| import org.eclipse.jdt.internal.ui.text.correction.LinkedCorrectionProposal; |
| import org.eclipse.jdt.ui.text.java.IInvocationContext; |
| import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; |
| import org.eclipse.jdt.ui.text.java.IProblemLocation; |
| import org.eclipse.jdt.ui.text.java.IQuickAssistProcessor; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jst.jsp.core.internal.java.JSPTranslationUtil; |
| import org.eclipse.swt.graphics.Image; |
| |
| /** |
| * This is a copy of |
| * org.eclipse.jdt.internal.ui.text.correction.QuickAssistProcessor with the |
| * following modifications: - replaced LocalRenameQuickAssistProposal with |
| * LocalRenameQuickAssistProposalJSP - replace ASTRewriteCorrectionProposal |
| * with ASTRewriteCorrectionProposalJSP |
| */ |
| public class QuickAssistProcessorJSP implements IQuickAssistProcessor { |
| private IDocument fDocument; |
| |
| public void setJSPDocument(IDocument document) { |
| fDocument = document; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jdt.internal.ui.text.correction.IAssistProcessor#hasAssists(org.eclipse.jdt.internal.ui.text.correction.IAssistContext) |
| */ |
| public boolean hasAssists(IInvocationContext context) throws CoreException { |
| ASTNode coveringNode = getCoveringNode(context); |
| if (coveringNode != null) { |
| return getCatchClauseToThrowsProposals(context, coveringNode, null) || getRenameLocalProposals(context, coveringNode, null, null) || getAssignToVariableProposals(context, coveringNode, null) || getUnWrapProposals(context, coveringNode, null) || getAssignParamToFieldProposals(context, coveringNode, null) || getJoinVariableProposals(context, coveringNode, null) || getAddFinallyProposals(context, coveringNode, null) || getAddElseProposals(context, coveringNode, null) || getSplitVariableProposals(context, coveringNode, null) || getAddBlockProposals(context, coveringNode, null) || getInvertEqualsProposal(context, coveringNode, null); |
| } |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jdt.internal.ui.text.correction.IAssistProcessor#getAssists(org.eclipse.jdt.internal.ui.text.correction.IAssistContext, |
| * org.eclipse.jdt.internal.ui.text.correction.IProblemLocation[]) |
| */ |
| public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblemLocation[] locations) throws CoreException { |
| ASTNode coveringNode = getCoveringNode(context); |
| if (coveringNode != null) { |
| ArrayList resultingCollections = new ArrayList(); |
| // quick assists that show up also if there is an error/warning |
| getRenameLocalProposals(context, coveringNode, locations, resultingCollections); |
| |
| if (noErrorsAtLocation(locations)) { |
| getCatchClauseToThrowsProposals(context, coveringNode, resultingCollections); |
| getAssignToVariableProposals(context, coveringNode, resultingCollections); |
| getAssignParamToFieldProposals(context, coveringNode, resultingCollections); |
| getUnWrapProposals(context, coveringNode, resultingCollections); |
| getSplitVariableProposals(context, coveringNode, resultingCollections); |
| getJoinVariableProposals(context, coveringNode, resultingCollections); |
| getAddFinallyProposals(context, coveringNode, resultingCollections); |
| getAddElseProposals(context, coveringNode, resultingCollections); |
| getAddBlockProposals(context, coveringNode, resultingCollections); |
| getInvertEqualsProposal(context, coveringNode, resultingCollections); |
| } |
| return (IJavaCompletionProposal[]) resultingCollections.toArray(new IJavaCompletionProposal[resultingCollections.size()]); |
| } |
| return null; |
| } |
| |
| private boolean noErrorsAtLocation(IProblemLocation[] locations) { |
| if (locations != null) { |
| for (int i = 0; i < locations.length; i++) { |
| if (locations[i].isError()) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| private boolean getJoinVariableProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| ASTNode parent = node.getParent(); |
| if (!(parent instanceof VariableDeclarationFragment)) { |
| return false; |
| } |
| VariableDeclarationFragment fragment = (VariableDeclarationFragment) parent; |
| |
| IVariableBinding binding = fragment.resolveBinding(); |
| if (fragment.getInitializer() != null || binding == null || binding.isField()) { |
| return false; |
| } |
| |
| if (!(fragment.getParent() instanceof VariableDeclarationStatement)) { |
| return false; |
| } |
| VariableDeclarationStatement statement = (VariableDeclarationStatement) fragment.getParent(); |
| |
| SimpleName[] names = LinkedNodeFinder.findByBinding(statement.getParent(), binding); |
| if (names.length <= 1 || names[0] != fragment.getName()) { |
| return false; |
| } |
| |
| SimpleName firstAccess = names[1]; |
| if (!(firstAccess.getParent() instanceof Assignment)) { |
| return false; |
| } |
| Assignment assignment = (Assignment) firstAccess.getParent(); |
| if (assignment.getLeftHandSide() != firstAccess) { |
| return false; |
| } |
| |
| ASTNode assignParent = assignment.getParent(); |
| if (!(assignParent instanceof ExpressionStatement || assignParent instanceof ForStatement && ((ForStatement) assignParent).initializers().contains(assignment))) { |
| return false; |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| AST ast = statement.getAST(); |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.joindeclaration.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL); |
| LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image); |
| |
| Expression placeholder = (Expression) rewrite.createMoveTarget(assignment.getRightHandSide()); |
| rewrite.set(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY, placeholder, null); |
| |
| if (assignParent instanceof ExpressionStatement) { |
| int statementParent = assignParent.getParent().getNodeType(); |
| if (statementParent == ASTNode.IF_STATEMENT || statementParent == ASTNode.WHILE_STATEMENT || statementParent == ASTNode.DO_STATEMENT || statementParent == ASTNode.FOR_STATEMENT) { |
| |
| Block block = ast.newBlock(); |
| rewrite.replace(assignParent, block, null); |
| } |
| else { |
| rewrite.remove(assignParent, null); |
| } |
| } |
| else { |
| rewrite.remove(assignment, null); |
| } |
| |
| proposal.setEndPosition(rewrite.track(fragment.getName())); |
| resultingCollections.add(proposal); |
| return true; |
| |
| } |
| |
| private boolean getSplitVariableProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| ASTNode parent = node.getParent(); |
| if (!(parent instanceof VariableDeclarationFragment)) { |
| return false; |
| } |
| VariableDeclarationFragment fragment = (VariableDeclarationFragment) parent; |
| |
| if (fragment.getInitializer() == null) { |
| return false; |
| } |
| |
| Statement statement; |
| ASTNode fragParent = fragment.getParent(); |
| if (fragParent instanceof VariableDeclarationStatement) { |
| statement = (VariableDeclarationStatement) fragParent; |
| } |
| else if (fragParent instanceof VariableDeclarationExpression) { |
| statement = (Statement) fragParent.getParent(); |
| } |
| else { |
| return false; |
| } |
| // statement is ForStatement or VariableDeclarationStatement |
| |
| ASTNode statementParent = statement.getParent(); |
| StructuralPropertyDescriptor property = statement.getLocationInParent(); |
| if (!property.isChildListProperty()) { |
| return false; |
| } |
| |
| List list = (List) statementParent.getStructuralProperty(property); |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| AST ast = statement.getAST(); |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.splitdeclaration.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 1, image); |
| |
| Statement newStatement; |
| int insertIndex = list.indexOf(statement); |
| |
| Expression placeholder = (Expression) rewrite.createMoveTarget(fragment.getInitializer()); |
| Assignment assignment = ast.newAssignment(); |
| assignment.setRightHandSide(placeholder); |
| assignment.setLeftHandSide(ast.newSimpleName(fragment.getName().getIdentifier())); |
| |
| if (statement instanceof VariableDeclarationStatement) { |
| newStatement = ast.newExpressionStatement(assignment); |
| insertIndex += 1; // add after declaration |
| |
| int modifiers = ((VariableDeclarationStatement) statement).getModifiers(); |
| if (Modifier.isFinal(modifiers)) { |
| rewrite.set(statement, VariableDeclarationStatement.MODIFIERS_PROPERTY, new Integer(modifiers & ~Modifier.FINAL), null); |
| } |
| } |
| else { |
| rewrite.replace(fragment.getParent(), assignment, null); |
| VariableDeclarationFragment newFrag = ast.newVariableDeclarationFragment(); |
| newFrag.setName(ast.newSimpleName(fragment.getName().getIdentifier())); |
| newFrag.setExtraDimensions(fragment.getExtraDimensions()); |
| |
| VariableDeclarationExpression oldVarDecl = (VariableDeclarationExpression) fragParent; |
| |
| VariableDeclarationStatement newVarDec = ast.newVariableDeclarationStatement(newFrag); |
| newVarDec.setType((Type) ASTNode.copySubtree(ast, oldVarDecl.getType())); |
| newVarDec.setModifiers(oldVarDecl.getModifiers() & ~Modifier.FINAL); |
| newStatement = newVarDec; |
| } |
| |
| ListRewrite listRewriter = rewrite.getListRewrite(statementParent, (ChildListPropertyDescriptor) property); |
| listRewriter.insertAt(newStatement, insertIndex, null); |
| |
| resultingCollections.add(proposal); |
| return true; |
| } |
| |
| private ASTNode getCoveringNode(IInvocationContext context) { |
| NodeFinder finder = new NodeFinder(context.getSelectionOffset(), context.getSelectionLength()); |
| context.getASTRoot().accept(finder); |
| return finder.getCoveringNode(); |
| } |
| |
| |
| private boolean getAssignToVariableProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| Statement statement = ASTResolving.findParentStatement(node); |
| if (!(statement instanceof ExpressionStatement)) { |
| return false; |
| } |
| ExpressionStatement expressionStatement = (ExpressionStatement) statement; |
| |
| Expression expression = expressionStatement.getExpression(); |
| if (expression.getNodeType() == ASTNode.ASSIGNMENT) { |
| return false; // too confusing and not helpful |
| } |
| |
| ITypeBinding typeBinding = expression.resolveTypeBinding(); |
| typeBinding = Bindings.normalizeTypeBinding(typeBinding); |
| if (typeBinding == null) { |
| return false; |
| } |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| ICompilationUnit cu = context.getCompilationUnit(); |
| |
| AssignToVariableAssistProposal localProposal = new AssignToVariableAssistProposal(cu, AssignToVariableAssistProposal.LOCAL, expressionStatement, typeBinding, 2); |
| resultingCollections.add(localProposal); |
| |
| ASTNode type = ASTResolving.findParentType(expression); |
| if (type != null) { |
| AssignToVariableAssistProposal fieldProposal = new AssignToVariableAssistProposal(cu, AssignToVariableAssistProposal.FIELD, expressionStatement, typeBinding, 1); |
| resultingCollections.add(fieldProposal); |
| } |
| return false; |
| |
| } |
| |
| private boolean getAssignParamToFieldProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| ASTNode parent = node.getParent(); |
| if (!(parent instanceof SingleVariableDeclaration) || !(parent.getParent() instanceof MethodDeclaration)) { |
| return false; |
| } |
| SingleVariableDeclaration paramDecl = (SingleVariableDeclaration) parent; |
| IVariableBinding binding = paramDecl.resolveBinding(); |
| |
| MethodDeclaration methodDecl = (MethodDeclaration) parent.getParent(); |
| if (binding == null || methodDecl.getBody() == null) { |
| return false; |
| } |
| ITypeBinding typeBinding = binding.getType(); |
| if (typeBinding == null) { |
| return false; |
| } |
| |
| if (resultingCollections != null) { |
| AssignToVariableAssistProposal fieldProposal = new AssignToVariableAssistProposal(context.getCompilationUnit(), paramDecl, typeBinding, 1); |
| resultingCollections.add(fieldProposal); |
| } |
| return true; |
| } |
| |
| private boolean getAddFinallyProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| TryStatement tryStatement = ASTResolving.findParentTryStatement(node); |
| if (tryStatement == null || tryStatement.getFinally() != null) { |
| return false; |
| } |
| Statement statement = ASTResolving.findParentStatement(node); |
| if (tryStatement != statement && tryStatement.getBody() != statement) { |
| return false; // an node inside a catch or finally block |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| AST ast = tryStatement.getAST(); |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| Block finallyBody = ast.newBlock(); |
| |
| rewrite.set(tryStatement, TryStatement.FINALLY_PROPERTY, finallyBody, null); |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.addfinallyblock.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 1, image); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| |
| private boolean getAddElseProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| Statement statement = ASTResolving.findParentStatement(node); |
| if (!(statement instanceof IfStatement)) { |
| return false; |
| } |
| IfStatement ifStatement = (IfStatement) statement; |
| if (ifStatement.getElseStatement() != null) { |
| return false; |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| AST ast = statement.getAST(); |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| Block body = ast.newBlock(); |
| |
| rewrite.set(ifStatement, IfStatement.ELSE_STATEMENT_PROPERTY, body, null); |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.addelseblock.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 1, image); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| |
| public static boolean getCatchClauseToThrowsProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| CatchClause catchClause = (CatchClause) ASTResolving.findAncestor(node, ASTNode.CATCH_CLAUSE); |
| if (catchClause == null) { |
| return false; |
| } |
| |
| Statement statement = ASTResolving.findParentStatement(node); |
| if (statement != catchClause.getParent() && statement != catchClause.getBody()) { |
| return false; // selection is in a statement inside the body |
| } |
| |
| Type type = catchClause.getException().getType(); |
| if (!type.isSimpleType()) { |
| return false; |
| } |
| |
| BodyDeclaration bodyDeclaration = ASTResolving.findParentBodyDeclaration(catchClause); |
| if (!(bodyDeclaration instanceof MethodDeclaration)) { |
| return false; |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| AST ast = bodyDeclaration.getAST(); |
| MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDeclaration; |
| { |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| |
| removeCatchBlock(rewrite, methodDeclaration, catchClause); |
| |
| ITypeBinding binding = type.resolveBinding(); |
| if (binding == null || isNotYetThrown(binding, methodDeclaration.thrownExceptions())) { |
| Name name = ((SimpleType) type).getName(); |
| Name newName = (Name) ASTNode.copySubtree(catchClause.getAST(), name); |
| |
| ListRewrite listRewriter = rewrite.getListRewrite(methodDeclaration, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY); |
| listRewriter.insertLast(newName, null); |
| } |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.catchclausetothrows.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 4, image); |
| resultingCollections.add(proposal); |
| } |
| { |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| |
| removeCatchBlock(rewrite, methodDeclaration, catchClause); |
| String label = CorrectionMessages.getString("QuickAssistProcessor.removecatchclause.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 5, image); |
| resultingCollections.add(proposal); |
| } |
| |
| return true; |
| } |
| |
| private static void removeCatchBlock(ASTRewrite rewrite, MethodDeclaration methodDeclaration, CatchClause catchClause) { |
| TryStatement tryStatement = (TryStatement) catchClause.getParent(); |
| if (tryStatement.catchClauses().size() > 1 || tryStatement.getFinally() != null) { |
| rewrite.remove(catchClause, null); |
| } |
| else { |
| Block block = tryStatement.getBody(); |
| List statements = block.statements(); |
| if (statements.size() > 0) { |
| ListRewrite listRewrite = rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY); |
| ASTNode first = (ASTNode) statements.get(0); |
| ASTNode last = (ASTNode) statements.get(statements.size() - 1); |
| ASTNode placeholder = listRewrite.createCopyTarget(first, last); |
| rewrite.replace(tryStatement, placeholder, null); |
| } |
| else { |
| rewrite.remove(tryStatement, null); |
| } |
| } |
| } |
| |
| private static boolean isNotYetThrown(ITypeBinding binding, List thrownExcpetions) { |
| for (int i = 0; i < thrownExcpetions.size(); i++) { |
| Name name = (Name) thrownExcpetions.get(i); |
| ITypeBinding elem = (ITypeBinding) name.resolveBinding(); |
| if (elem != null) { |
| if (Bindings.isSuperType(elem, binding)) { // existing |
| // exception is |
| // base class of |
| // new |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| |
| private boolean getRenameLocalProposals(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection resultingCollections) { |
| if (!(node instanceof SimpleName)) { |
| return false; |
| } |
| SimpleName name = (SimpleName) node; |
| IBinding binding = name.resolveBinding(); |
| if (binding != null && binding.getKind() == IBinding.PACKAGE) { |
| return false; |
| } |
| |
| if (locations != null) { |
| for (int i = 0; i < locations.length; i++) { |
| switch (locations[i].getProblemId()) { |
| case IProblem.LocalVariableHidingLocalVariable : |
| case IProblem.LocalVariableHidingField : |
| case IProblem.FieldHidingLocalVariable : |
| case IProblem.FieldHidingField : |
| case IProblem.ArgumentHidingLocalVariable : |
| case IProblem.ArgumentHidingField : |
| return false; |
| } |
| } |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| LocalRenameQuickAssistProposalJSP proposal = new LocalRenameQuickAssistProposalJSP(context.getCompilationUnit(), name); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| |
| private ASTNode getCopyOfInner(ASTRewrite rewrite, ASTNode statement) { |
| if (statement.getNodeType() == ASTNode.BLOCK) { |
| Block block = (Block) statement; |
| List innerStatements = block.statements(); |
| int nStatements = innerStatements.size(); |
| if (nStatements == 1) { |
| return rewrite.createCopyTarget(((ASTNode) innerStatements.get(0))); |
| } |
| else if (nStatements > 1) { |
| ListRewrite listRewrite = rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY); |
| ASTNode first = (ASTNode) innerStatements.get(0); |
| ASTNode last = (ASTNode) innerStatements.get(nStatements - 1); |
| return listRewrite.createCopyTarget(first, last); |
| } |
| return null; |
| } |
| else { |
| return rewrite.createCopyTarget(statement); |
| } |
| } |
| |
| |
| private boolean getUnWrapProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| ASTNode outer = node; |
| |
| Block block = null; |
| if (outer.getNodeType() == ASTNode.BLOCK) { |
| block = (Block) outer; |
| outer = block.getParent(); |
| } |
| |
| ASTNode body = null; |
| String label = null; |
| if (outer instanceof IfStatement) { |
| IfStatement ifStatement = (IfStatement) outer; |
| Statement elseBlock = ifStatement.getElseStatement(); |
| if (elseBlock == null || ((elseBlock instanceof Block) && ((Block) elseBlock).statements().isEmpty())) { |
| body = ifStatement.getThenStatement(); |
| } |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.ifstatement"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof WhileStatement) { |
| body = ((WhileStatement) outer).getBody(); |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.whilestatement"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof ForStatement) { |
| body = ((ForStatement) outer).getBody(); |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.forstatement"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof DoStatement) { |
| body = ((DoStatement) outer).getBody(); |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.dostatement"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof TryStatement) { |
| TryStatement tryStatement = (TryStatement) outer; |
| if (tryStatement.catchClauses().isEmpty()) { |
| body = tryStatement.getBody(); |
| } |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.trystatement"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof AnonymousClassDeclaration) { |
| List decls = ((AnonymousClassDeclaration) outer).bodyDeclarations(); |
| for (int i = 0; i < decls.size(); i++) { |
| ASTNode elem = (ASTNode) decls.get(i); |
| if (elem instanceof MethodDeclaration) { |
| Block curr = ((MethodDeclaration) elem).getBody(); |
| if (curr != null && !curr.statements().isEmpty()) { |
| if (body != null) { |
| return false; |
| } |
| body = curr; |
| } |
| } |
| else if (elem instanceof TypeDeclaration) { |
| return false; |
| } |
| } |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.anonymous"); //$NON-NLS-1$ |
| outer = ASTResolving.findParentStatement(outer); |
| } |
| else if (outer instanceof Block) { |
| // -> a block in a block |
| body = block; |
| outer = block; |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.block"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof ParenthesizedExpression) { |
| ParenthesizedExpression expression = (ParenthesizedExpression) outer; |
| body = expression.getExpression(); |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.parenthesis"); //$NON-NLS-1$ |
| } |
| else if (outer instanceof MethodInvocation) { |
| MethodInvocation invocation = (MethodInvocation) outer; |
| if (invocation.arguments().size() == 1) { |
| body = (ASTNode) invocation.arguments().get(0); |
| if (invocation.getParent().getNodeType() == ASTNode.EXPRESSION_STATEMENT) { |
| int kind = body.getNodeType(); |
| if (kind != ASTNode.ASSIGNMENT && kind != ASTNode.PREFIX_EXPRESSION && kind != ASTNode.POSTFIX_EXPRESSION && kind != ASTNode.METHOD_INVOCATION && kind != ASTNode.SUPER_METHOD_INVOCATION) { |
| body = null; |
| } |
| } |
| label = CorrectionMessages.getString("QuickAssistProcessor.unwrap.methodinvocation"); //$NON-NLS-1$ |
| } |
| } |
| if (body == null) { |
| return false; |
| } |
| ASTRewrite rewrite = ASTRewrite.create(outer.getAST()); |
| ASTNode inner = getCopyOfInner(rewrite, body); |
| if (inner == null) { |
| return false; |
| } |
| if (resultingCollections == null) { |
| return true; |
| } |
| |
| JSPTranslationUtil translationUtil = new JSPTranslationUtil(fDocument); |
| if (!translationUtil.getTranslation().javaSpansMultipleJspPartitions(outer.getStartPosition(), outer.getLength())) { |
| rewrite.replace(outer, inner, null); |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION); |
| ASTRewriteCorrectionProposalJSP proposal = new ASTRewriteCorrectionProposalJSP(label, context.getCompilationUnit(), rewrite, 1, image); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| private static boolean isControlStatementWithBlock(ASTNode node) { |
| switch (node.getNodeType()) { |
| case ASTNode.IF_STATEMENT : |
| case ASTNode.WHILE_STATEMENT : |
| case ASTNode.FOR_STATEMENT : |
| case ASTNode.DO_STATEMENT : |
| return true; |
| default : |
| return false; |
| } |
| } |
| |
| |
| private boolean getAddBlockProposals(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| Statement statement = ASTResolving.findParentStatement(node); |
| if (statement == null) { |
| return false; |
| } |
| |
| if (!isControlStatementWithBlock(statement)) { |
| if (!isControlStatementWithBlock(statement.getParent())) { |
| return false; |
| } |
| int statementStart = statement.getStartPosition(); |
| int statementEnd = statementStart + statement.getLength(); |
| |
| int offset = context.getSelectionOffset(); |
| int length = context.getSelectionLength(); |
| if (length == 0) { |
| if (offset != statementEnd) { // cursor at end |
| return false; |
| } |
| } |
| else { |
| if (offset > statementStart || offset + length < statementEnd) { // statement |
| // selected |
| return false; |
| } |
| } |
| statement = (Statement) statement.getParent(); |
| } |
| |
| StructuralPropertyDescriptor childProperty = null; |
| ASTNode child = null; |
| switch (statement.getNodeType()) { |
| case ASTNode.IF_STATEMENT : |
| int selectionStart = context.getSelectionOffset(); |
| int selectionEnd = context.getSelectionOffset() + context.getSelectionLength(); |
| ASTNode then = ((IfStatement) statement).getThenStatement(); |
| if (selectionEnd <= then.getStartPosition() + then.getLength()) { |
| if (!(then instanceof Block)) { |
| childProperty = IfStatement.THEN_STATEMENT_PROPERTY; |
| child = then; |
| } |
| } |
| else if (selectionStart >= then.getStartPosition() + then.getLength()) { |
| ASTNode elseStatement = ((IfStatement) statement).getElseStatement(); |
| if (!(elseStatement instanceof Block)) { |
| childProperty = IfStatement.ELSE_STATEMENT_PROPERTY; |
| child = elseStatement; |
| } |
| } |
| break; |
| case ASTNode.WHILE_STATEMENT : |
| ASTNode whileBody = ((WhileStatement) statement).getBody(); |
| if (!(whileBody instanceof Block)) { |
| childProperty = WhileStatement.BODY_PROPERTY; |
| child = whileBody; |
| } |
| break; |
| case ASTNode.FOR_STATEMENT : |
| ASTNode forBody = ((ForStatement) statement).getBody(); |
| if (!(forBody instanceof Block)) { |
| childProperty = ForStatement.BODY_PROPERTY; |
| child = forBody; |
| } |
| break; |
| case ASTNode.DO_STATEMENT : |
| ASTNode doBody = ((DoStatement) statement).getBody(); |
| if (!(doBody instanceof Block)) { |
| childProperty = DoStatement.BODY_PROPERTY; |
| child = doBody; |
| } |
| break; |
| default : |
| } |
| if (child == null) { |
| return false; |
| } |
| |
| if (resultingCollections == null) { |
| return true; |
| } |
| AST ast = statement.getAST(); |
| ASTRewrite rewrite = ASTRewrite.create(ast); |
| |
| ASTNode childPlaceholder = rewrite.createMoveTarget(child); |
| Block replacingBody = ast.newBlock(); |
| replacingBody.statements().add(childPlaceholder); |
| rewrite.set(statement, childProperty, replacingBody, null); |
| |
| String label; |
| if (childProperty == IfStatement.THEN_STATEMENT_PROPERTY) { |
| label = CorrectionMessages.getString("QuickAssistProcessor.replacethenwithblock.description");//$NON-NLS-1$ |
| } |
| else if (childProperty == IfStatement.ELSE_STATEMENT_PROPERTY) { |
| label = CorrectionMessages.getString("QuickAssistProcessor.replaceelsewithblock.description");//$NON-NLS-1$ |
| } |
| else { |
| label = CorrectionMessages.getString("QuickAssistProcessor.replacebodywithblock.description");//$NON-NLS-1$ |
| } |
| |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, 10, image); |
| proposal.setEndPosition(rewrite.track(child)); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| |
| private boolean getInvertEqualsProposal(IInvocationContext context, ASTNode node, Collection resultingCollections) { |
| ASTNode parent = node.getParent(); |
| if (!(parent instanceof MethodInvocation)) { |
| return false; |
| } |
| MethodInvocation method = (MethodInvocation) parent; |
| if (!"equals".equals(method.getName().getIdentifier())) { //$NON-NLS-1$ |
| return false; |
| } |
| List arguments = method.arguments(); |
| if (arguments.size() != 1) { //overloaded equals w/ more than 1 arg |
| return false; |
| } |
| Expression right = (Expression) arguments.get(0); |
| ITypeBinding binding = right.resolveTypeBinding(); |
| if (!(binding.isClass() || binding.isInterface())) { //overloaded |
| // equals w/ |
| // non-class/interface |
| // arg or null |
| return false; |
| } |
| Expression left = method.getExpression(); |
| |
| AST ast = method.getAST(); |
| ASTRewrite rewrite; |
| if (left == null) { // equals(x) -> x.equals(this) |
| rewrite = ASTRewrite.create(ast); |
| MethodInvocation replacement = ast.newMethodInvocation(); |
| replacement.setName((SimpleName) rewrite.createCopyTarget(method.getName())); |
| replacement.arguments().add(ast.newThisExpression()); |
| replacement.setExpression((Expression) rewrite.createCopyTarget(right)); |
| rewrite.replace(method, replacement, null); |
| } |
| else if (right instanceof ThisExpression) { // x.equals(this) -> |
| // equals(x) |
| rewrite = ASTRewrite.create(ast); |
| MethodInvocation replacement = rewrite.getAST().newMethodInvocation(); |
| replacement.setName((SimpleName) rewrite.createCopyTarget(method.getName())); |
| replacement.arguments().add(rewrite.createCopyTarget(left)); |
| rewrite.replace(method, replacement, null); |
| } |
| else { |
| rewrite = ASTRewrite.create(ast); |
| if (left instanceof ParenthesizedExpression) { |
| Expression ex = ((ParenthesizedExpression) left).getExpression(); |
| rewrite.replace(right, rewrite.createCopyTarget(ex), null); |
| } |
| else { |
| rewrite.replace(right, rewrite.createCopyTarget(left), null); |
| } |
| if ((right instanceof CastExpression) || (right instanceof Assignment) || (right instanceof ConditionalExpression) || (right instanceof InfixExpression)) { |
| ParenthesizedExpression paren = rewrite.getAST().newParenthesizedExpression(); |
| paren.setExpression((Expression) rewrite.createCopyTarget(right)); |
| rewrite.replace(left, paren, null); |
| } |
| else { |
| rewrite.replace(left, rewrite.createCopyTarget(right), null); |
| } |
| } |
| |
| String label = CorrectionMessages.getString("QuickAssistProcessor.invertequals.description"); //$NON-NLS-1$ |
| Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| |
| LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image); |
| resultingCollections.add(proposal); |
| return true; |
| } |
| } |