Search in sources :

Example 1 with LinkedCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class ReturnTypeSubProcessor method addVoidMethodReturnsProposals.

public static void addVoidMethodReturnsProposals(IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals) {
    ICompilationUnit cu = context.getCompilationUnit();
    CompilationUnit astRoot = context.getASTRoot();
    ASTNode selectedNode = problem.getCoveringNode(astRoot);
    if (selectedNode == null) {
        return;
    }
    BodyDeclaration decl = ASTResolving.findParentBodyDeclaration(selectedNode);
    if (decl instanceof MethodDeclaration && selectedNode.getNodeType() == ASTNode.RETURN_STATEMENT) {
        ReturnStatement returnStatement = (ReturnStatement) selectedNode;
        Expression expr = returnStatement.getExpression();
        if (expr != null) {
            AST ast = astRoot.getAST();
            ITypeBinding binding = Bindings.normalizeTypeBinding(expr.resolveTypeBinding());
            if (binding == null) {
                // $NON-NLS-1$
                binding = ast.resolveWellKnownType("java.lang.Object");
            }
            if (binding.isWildcardType()) {
                binding = ASTResolving.normalizeWildcardType(binding, true, ast);
            }
            MethodDeclaration methodDeclaration = (MethodDeclaration) decl;
            ASTRewrite rewrite = ASTRewrite.create(ast);
            String label = Messages.format(CorrectionMessages.ReturnTypeSubProcessor_voidmethodreturns_description, BindingLabelProviderCore.getBindingLabel(binding, BindingLabelProviderCore.DEFAULT_TEXTFLAGS));
            LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.QuickFix, cu, rewrite, IProposalRelevance.VOID_METHOD_RETURNS);
            ImportRewrite imports = proposal.createImportRewrite(astRoot);
            ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(methodDeclaration, imports);
            Type newReturnType = imports.addImport(binding, ast, importRewriteContext, TypeLocation.RETURN_TYPE);
            if (methodDeclaration.isConstructor()) {
                rewrite.set(methodDeclaration, MethodDeclaration.CONSTRUCTOR_PROPERTY, Boolean.FALSE, null);
                rewrite.set(methodDeclaration, MethodDeclaration.RETURN_TYPE2_PROPERTY, newReturnType, null);
            } else {
                rewrite.replace(methodDeclaration.getReturnType2(), newReturnType, null);
            }
            // $NON-NLS-1$
            String key = "return_type";
            proposal.addLinkedPosition(rewrite.track(newReturnType), true, key);
            ITypeBinding[] bindings = ASTResolving.getRelaxingTypes(ast, binding);
            for (int i = 0; i < bindings.length; i++) {
                proposal.addLinkedPositionProposal(key, bindings[i]);
            }
            Javadoc javadoc = methodDeclaration.getJavadoc();
            if (javadoc != null) {
                TagElement newTag = ast.newTagElement();
                newTag.setTagName(TagElement.TAG_RETURN);
                TextElement commentStart = ast.newTextElement();
                newTag.fragments().add(commentStart);
                JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY), newTag, null);
                // $NON-NLS-1$
                proposal.addLinkedPosition(rewrite.track(commentStart), false, "comment_start");
            }
            proposals.add(proposal);
        }
        ASTRewrite rewrite = ASTRewrite.create(decl.getAST());
        rewrite.remove(returnStatement.getExpression(), null);
        String label = CorrectionMessages.ReturnTypeSubProcessor_removereturn_description;
        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, CodeActionKind.QuickFix, cu, rewrite, IProposalRelevance.CHANGE_TO_RETURN);
        proposals.add(proposal);
    }
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) AST(org.eclipse.jdt.core.dom.AST) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) Javadoc(org.eclipse.jdt.core.dom.Javadoc) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) Type(org.eclipse.jdt.core.dom.Type) PrimitiveType(org.eclipse.jdt.core.dom.PrimitiveType) TextElement(org.eclipse.jdt.core.dom.TextElement) ImportRewriteContext(org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) Expression(org.eclipse.jdt.core.dom.Expression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ReturnStatement(org.eclipse.jdt.core.dom.ReturnStatement) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) TagElement(org.eclipse.jdt.core.dom.TagElement) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration)

Example 2 with LinkedCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class ReturnTypeSubProcessor method addMissingReturnTypeProposals.

public static void addMissingReturnTypeProposals(IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals) {
    ICompilationUnit cu = context.getCompilationUnit();
    CompilationUnit astRoot = context.getASTRoot();
    ASTNode selectedNode = problem.getCoveringNode(astRoot);
    if (selectedNode == null) {
        return;
    }
    BodyDeclaration decl = ASTResolving.findParentBodyDeclaration(selectedNode);
    if (decl instanceof MethodDeclaration) {
        MethodDeclaration methodDeclaration = (MethodDeclaration) decl;
        ReturnStatementCollector eval = new ReturnStatementCollector();
        decl.accept(eval);
        AST ast = astRoot.getAST();
        ITypeBinding typeBinding = eval.getTypeBinding(decl.getAST());
        typeBinding = Bindings.normalizeTypeBinding(typeBinding);
        if (typeBinding == null) {
            // $NON-NLS-1$
            typeBinding = ast.resolveWellKnownType("void");
        }
        if (typeBinding.isWildcardType()) {
            typeBinding = ASTResolving.normalizeWildcardType(typeBinding, true, ast);
        }
        ASTRewrite rewrite = ASTRewrite.create(ast);
        String label = Messages.format(CorrectionMessages.ReturnTypeSubProcessor_missingreturntype_description, BindingLabelProviderCore.getBindingLabel(typeBinding, BindingLabelProviderCore.DEFAULT_TEXTFLAGS));
        LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.QuickFix, cu, rewrite, IProposalRelevance.MISSING_RETURN_TYPE);
        ImportRewrite imports = proposal.createImportRewrite(astRoot);
        ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(decl, imports);
        Type type = imports.addImport(typeBinding, ast, importRewriteContext, TypeLocation.RETURN_TYPE);
        rewrite.set(methodDeclaration, MethodDeclaration.RETURN_TYPE2_PROPERTY, type, null);
        rewrite.set(methodDeclaration, MethodDeclaration.CONSTRUCTOR_PROPERTY, Boolean.FALSE, null);
        Javadoc javadoc = methodDeclaration.getJavadoc();
        if (javadoc != null && typeBinding != null) {
            TagElement newTag = ast.newTagElement();
            newTag.setTagName(TagElement.TAG_RETURN);
            TextElement commentStart = ast.newTextElement();
            newTag.fragments().add(commentStart);
            JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY), newTag, null);
            // $NON-NLS-1$
            proposal.addLinkedPosition(rewrite.track(commentStart), false, "comment_start");
        }
        // $NON-NLS-1$
        String key = "return_type";
        proposal.addLinkedPosition(rewrite.track(type), true, key);
        if (typeBinding != null) {
            ITypeBinding[] bindings = ASTResolving.getRelaxingTypes(ast, typeBinding);
            for (int i = 0; i < bindings.length; i++) {
                proposal.addLinkedPositionProposal(key, bindings[i]);
            }
        }
        proposals.add(proposal);
        // change to constructor
        ASTNode parentType = ASTResolving.findParentType(decl);
        if (parentType instanceof AbstractTypeDeclaration) {
            boolean isInterface = parentType instanceof TypeDeclaration && ((TypeDeclaration) parentType).isInterface();
            if (!isInterface) {
                String constructorName = ((AbstractTypeDeclaration) parentType).getName().getIdentifier();
                ASTNode nameNode = methodDeclaration.getName();
                label = Messages.format(CorrectionMessages.ReturnTypeSubProcessor_wrongconstructorname_description, BasicElementLabels.getJavaElementName(constructorName));
                proposals.add(new ReplaceCorrectionProposal(label, cu, nameNode.getStartPosition(), nameNode.getLength(), constructorName, IProposalRelevance.CHANGE_TO_CONSTRUCTOR));
            }
        }
    }
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) AST(org.eclipse.jdt.core.dom.AST) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) Javadoc(org.eclipse.jdt.core.dom.Javadoc) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) Type(org.eclipse.jdt.core.dom.Type) PrimitiveType(org.eclipse.jdt.core.dom.PrimitiveType) TextElement(org.eclipse.jdt.core.dom.TextElement) ImportRewriteContext(org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) TagElement(org.eclipse.jdt.core.dom.TagElement) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration) AnnotationTypeDeclaration(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration) AbstractTypeDeclaration(org.eclipse.jdt.core.dom.AbstractTypeDeclaration) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration) AbstractTypeDeclaration(org.eclipse.jdt.core.dom.AbstractTypeDeclaration) ReplaceCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ReplaceCorrectionProposal)

Example 3 with LinkedCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class InvertBooleanUtility method getInvertVariableProposal.

public static ChangeCorrectionProposal getInvertVariableProposal(CodeActionParams params, IInvocationContext context, ASTNode covering, boolean returnAsCommand) {
    // cursor should be placed on variable name
    if (!(covering instanceof SimpleName)) {
        return null;
    }
    SimpleName coveringName = (SimpleName) covering;
    if (!coveringName.isDeclaration()) {
        return null;
    }
    // prepare bindings
    final IBinding variableBinding = coveringName.resolveBinding();
    if (!(variableBinding instanceof IVariableBinding)) {
        return null;
    }
    IVariableBinding binding = (IVariableBinding) variableBinding;
    if (binding.isField()) {
        return null;
    }
    // we operate only on boolean variable
    if (!isBoolean(coveringName)) {
        return null;
    }
    String label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseBooleanVariable;
    if (returnAsCommand) {
        return new CUCorrectionCommandProposal(label, CodeActionKind.Refactor, context.getCompilationUnit(), IProposalRelevance.INVERSE_BOOLEAN_VARIABLE, RefactorProposalUtility.APPLY_REFACTORING_COMMAND_ID, Arrays.asList(INVERT_VARIABLE_COMMAND, params));
    }
    final AST ast = covering.getAST();
    // find linked nodes
    final MethodDeclaration method = ASTResolving.findParentMethodDeclaration(covering);
    SimpleName[] linkedNodes = LinkedNodeFinder.findByBinding(method, variableBinding);
    // 
    final ASTRewrite rewrite = ASTRewrite.create(ast);
    // create proposal
    // $NON-NLS-1$
    final String KEY_NAME = "name";
    final LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.Refactor, context.getCompilationUnit(), rewrite, IProposalRelevance.INVERSE_BOOLEAN_VARIABLE);
    // prepare new variable identifier
    final String oldIdentifier = coveringName.getIdentifier();
    // $NON-NLS-1$
    final String notString = Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, "");
    final String newIdentifier;
    if (oldIdentifier.startsWith(notString)) {
        int notLength = notString.length();
        if (oldIdentifier.length() > notLength) {
            newIdentifier = Character.toLowerCase(oldIdentifier.charAt(notLength)) + oldIdentifier.substring(notLength + 1);
        } else {
            newIdentifier = oldIdentifier;
        }
    } else {
        newIdentifier = Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, Character.toUpperCase(oldIdentifier.charAt(0)) + oldIdentifier.substring(1));
    }
    // 
    proposal.addLinkedPositionProposal(KEY_NAME, newIdentifier);
    proposal.addLinkedPositionProposal(KEY_NAME, oldIdentifier);
    // iterate over linked nodes and replace variable references with negated reference
    final HashSet<SimpleName> renamedNames = new HashSet<>();
    for (int i = 0; i < linkedNodes.length; i++) {
        SimpleName name = linkedNodes[i];
        if (renamedNames.contains(name)) {
            continue;
        }
        // prepare new name with new identifier
        SimpleName newName = ast.newSimpleName(newIdentifier);
        proposal.addLinkedPosition(rewrite.track(newName), name == coveringName, KEY_NAME);
        // 
        StructuralPropertyDescriptor location = name.getLocationInParent();
        if (location == SingleVariableDeclaration.NAME_PROPERTY) {
            // set new name
            rewrite.replace(name, newName, null);
        } else if (location == Assignment.LEFT_HAND_SIDE_PROPERTY) {
            Assignment assignment = (Assignment) name.getParent();
            Expression expression = assignment.getRightHandSide();
            int exStart = expression.getStartPosition();
            int exEnd = exStart + expression.getLength();
            // collect all names that are used in assignments
            HashSet<SimpleName> overlapNames = new HashSet<>();
            for (int j = 0; j < linkedNodes.length; j++) {
                SimpleName name2 = linkedNodes[j];
                if (name2 == null) {
                    continue;
                }
                int name2Start = name2.getStartPosition();
                if (exStart <= name2Start && name2Start < exEnd) {
                    overlapNames.add(name2);
                }
            }
            // prepare inverted expression
            SimpleNameRenameProvider provider = new SimpleNameRenameProvider() {

                @Override
                public SimpleName getRenamed(SimpleName simpleName) {
                    if (simpleName.resolveBinding() == variableBinding) {
                        renamedNames.add(simpleName);
                        return ast.newSimpleName(newIdentifier);
                    }
                    return null;
                }
            };
            Expression inversedExpression = getInversedExpression(rewrite, expression, provider);
            // if any name was not renamed during expression inverting, we can not already rename it, so fail to create assist
            for (Iterator<SimpleName> iter = overlapNames.iterator(); iter.hasNext(); ) {
                Object o = iter.next();
                if (!renamedNames.contains(o)) {
                    return null;
                }
            }
            // check operator and replace if needed
            Assignment.Operator operator = assignment.getOperator();
            if (operator == Assignment.Operator.BIT_AND_ASSIGN) {
                Assignment newAssignment = ast.newAssignment();
                newAssignment.setLeftHandSide(newName);
                newAssignment.setRightHandSide(inversedExpression);
                newAssignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
                rewrite.replace(assignment, newAssignment, null);
            } else if (operator == Assignment.Operator.BIT_OR_ASSIGN) {
                Assignment newAssignment = ast.newAssignment();
                newAssignment.setLeftHandSide(newName);
                newAssignment.setRightHandSide(inversedExpression);
                newAssignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
                rewrite.replace(assignment, newAssignment, null);
            } else {
                rewrite.replace(expression, inversedExpression, null);
                // set new name
                rewrite.replace(name, newName, null);
            }
        } else if (location == VariableDeclarationFragment.NAME_PROPERTY) {
            // replace initializer for variable
            VariableDeclarationFragment vdf = (VariableDeclarationFragment) name.getParent();
            Expression expression = vdf.getInitializer();
            if (expression != null) {
                rewrite.replace(expression, getInversedExpression(rewrite, expression), null);
            }
            // set new name
            rewrite.replace(name, newName, null);
        } else if (name.getParent() instanceof PrefixExpression && ((PrefixExpression) name.getParent()).getOperator() == PrefixExpression.Operator.NOT) {
            rewrite.replace(name.getParent(), newName, null);
        } else {
            PrefixExpression expression = ast.newPrefixExpression();
            expression.setOperator(PrefixExpression.Operator.NOT);
            expression.setOperand(newName);
            rewrite.replace(name, expression, null);
        }
    }
    return proposal;
}
Also used : Operator(org.eclipse.jdt.core.dom.InfixExpression.Operator) AST(org.eclipse.jdt.core.dom.AST) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) SimpleName(org.eclipse.jdt.core.dom.SimpleName) IBinding(org.eclipse.jdt.core.dom.IBinding) CUCorrectionCommandProposal(org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal) IVariableBinding(org.eclipse.jdt.core.dom.IVariableBinding) Assignment(org.eclipse.jdt.core.dom.Assignment) ConditionalExpression(org.eclipse.jdt.core.dom.ConditionalExpression) InstanceofExpression(org.eclipse.jdt.core.dom.InstanceofExpression) Expression(org.eclipse.jdt.core.dom.Expression) InfixExpression(org.eclipse.jdt.core.dom.InfixExpression) ParenthesizedExpression(org.eclipse.jdt.core.dom.ParenthesizedExpression) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) Iterator(java.util.Iterator) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) HashSet(java.util.HashSet) StructuralPropertyDescriptor(org.eclipse.jdt.core.dom.StructuralPropertyDescriptor)

Example 4 with LinkedCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class QuickAssistProcessor method getTryWithResourceProposals.

public static boolean getTryWithResourceProposals(IInvocationContext context, ASTNode node, ArrayList<ASTNode> coveredNodes, Collection<ChangeCorrectionProposal> resultingCollections) throws IllegalArgumentException, CoreException {
    if (!JavaModelUtil.is1d8OrHigher(context.getCompilationUnit().getJavaProject())) {
        return false;
    }
    ASTNode parentStatement = ASTResolving.findAncestor(node, ASTNode.VARIABLE_DECLARATION_STATEMENT);
    if (!(parentStatement instanceof VariableDeclarationStatement) && !(parentStatement instanceof ExpressionStatement) && !(node instanceof SimpleName) && (coveredNodes == null || coveredNodes.isEmpty())) {
        return false;
    }
    List<ASTNode> coveredStatements = new ArrayList<>();
    if (coveredNodes == null || coveredNodes.isEmpty() && parentStatement != null) {
        coveredStatements.add(parentStatement);
    } else {
        for (ASTNode coveredNode : coveredNodes) {
            Statement statement = ASTResolving.findParentStatement(coveredNode);
            if (statement == null) {
                continue;
            }
            if (!coveredStatements.contains(statement)) {
                coveredStatements.add(statement);
            }
        }
    }
    List<ASTNode> coveredAutoClosableNodes = QuickAssistProcessorUtil.getCoveredAutoClosableNodes(coveredStatements);
    if (coveredAutoClosableNodes.isEmpty()) {
        return false;
    }
    ASTNode parentBodyDeclaration = (node instanceof Block || node instanceof BodyDeclaration) ? node : ASTNodes.getFirstAncestorOrNull(node, Block.class, BodyDeclaration.class);
    int start = coveredAutoClosableNodes.get(0).getStartPosition();
    int end = start;
    for (ASTNode astNode : coveredAutoClosableNodes) {
        int endPosition = QuickAssistProcessorUtil.findEndPostion(astNode);
        end = Math.max(end, endPosition);
    }
    // recursive loop to find all nodes affected by wrapping in try block
    List<ASTNode> nodesInRange = SurroundWithTryWithResourcesRefactoringCore.findNodesInRange(parentBodyDeclaration, start, end);
    int oldEnd = end;
    while (true) {
        int newEnd = oldEnd;
        for (ASTNode astNode : nodesInRange) {
            int endPosition = QuickAssistProcessorUtil.findEndPostion(astNode);
            newEnd = Math.max(newEnd, endPosition);
        }
        if (newEnd > oldEnd) {
            oldEnd = newEnd;
            nodesInRange = SurroundWithTryWithResourcesRefactoringCore.findNodesInRange(parentBodyDeclaration, start, newEnd);
            continue;
        }
        break;
    }
    nodesInRange.removeAll(coveredAutoClosableNodes);
    CompilationUnit cu = (CompilationUnit) node.getRoot();
    IBuffer buffer = context.getCompilationUnit().getBuffer();
    AST ast = node.getAST();
    ASTRewrite rewrite = ASTRewrite.create(ast);
    boolean modifyExistingTry = false;
    TryStatement newTryStatement = null;
    Block newTryBody = null;
    TryStatement enclosingTry = (TryStatement) ASTResolving.findAncestor(node, ASTNode.TRY_STATEMENT);
    ListRewrite resourcesRewriter = null;
    ListRewrite clausesRewriter = null;
    if (enclosingTry == null || enclosingTry.getBody() == null || enclosingTry.getBody().statements().get(0) != coveredNodes.get(0)) {
        newTryStatement = ast.newTryStatement();
        newTryBody = ast.newBlock();
        newTryStatement.setBody(newTryBody);
    } else {
        modifyExistingTry = true;
        resourcesRewriter = rewrite.getListRewrite(enclosingTry, TryStatement.RESOURCES2_PROPERTY);
        clausesRewriter = rewrite.getListRewrite(enclosingTry, TryStatement.CATCH_CLAUSES_PROPERTY);
    }
    ICompilationUnit icu = context.getCompilationUnit();
    ASTNode lastNode = nodesInRange.isEmpty() ? coveredAutoClosableNodes.get(coveredAutoClosableNodes.size() - 1) : nodesInRange.get(nodesInRange.size() - 1);
    Selection selection = Selection.createFromStartLength(start, lastNode.getStartPosition() - start + lastNode.getLength());
    SurroundWithTryWithResourcesAnalyzer analyzer = new SurroundWithTryWithResourcesAnalyzer(icu, selection);
    cu.accept(analyzer);
    ITypeBinding[] exceptions = analyzer.getExceptions(analyzer.getSelection());
    List<ITypeBinding> allExceptions = new ArrayList<>(Arrays.asList(exceptions));
    int resourceCount = 0;
    for (ASTNode coveredNode : coveredAutoClosableNodes) {
        ASTNode findAncestor = ASTResolving.findAncestor(coveredNode, ASTNode.VARIABLE_DECLARATION_STATEMENT);
        if (findAncestor == null) {
            findAncestor = ASTResolving.findAncestor(coveredNode, ASTNode.ASSIGNMENT);
        }
        if (findAncestor instanceof VariableDeclarationStatement) {
            VariableDeclarationStatement vds = (VariableDeclarationStatement) findAncestor;
            String commentToken = null;
            int extendedStatementStart = cu.getExtendedStartPosition(vds);
            if (vds.getStartPosition() > extendedStatementStart) {
                commentToken = buffer.getText(extendedStatementStart, vds.getStartPosition() - extendedStatementStart);
            }
            Type type = vds.getType();
            ITypeBinding typeBinding = type.resolveBinding();
            if (typeBinding != null) {
                IMethodBinding close = SurroundWithTryWithResourcesRefactoringCore.findAutocloseMethod(typeBinding);
                if (close != null) {
                    for (ITypeBinding exceptionType : close.getExceptionTypes()) {
                        if (!allExceptions.contains(exceptionType)) {
                            allExceptions.add(exceptionType);
                        }
                    }
                }
            }
            String typeName = buffer.getText(type.getStartPosition(), type.getLength());
            for (Object object : vds.fragments()) {
                VariableDeclarationFragment variableDeclarationFragment = (VariableDeclarationFragment) object;
                VariableDeclarationFragment newVariableDeclarationFragment = ast.newVariableDeclarationFragment();
                SimpleName name = variableDeclarationFragment.getName();
                if (commentToken == null) {
                    int extendedStart = cu.getExtendedStartPosition(variableDeclarationFragment);
                    commentToken = buffer.getText(extendedStart, variableDeclarationFragment.getStartPosition() - extendedStart);
                }
                commentToken = Strings.trimTrailingTabsAndSpaces(commentToken);
                newVariableDeclarationFragment.setName(ast.newSimpleName(name.getIdentifier()));
                Expression newExpression = null;
                Expression initializer = variableDeclarationFragment.getInitializer();
                if (initializer == null) {
                    rewrite.remove(coveredNode, null);
                    continue;
                } else {
                    newExpression = (Expression) rewrite.createMoveTarget(initializer);
                }
                newVariableDeclarationFragment.setInitializer(newExpression);
                VariableDeclarationExpression newVariableDeclarationExpression = ast.newVariableDeclarationExpression(newVariableDeclarationFragment);
                newVariableDeclarationExpression.setType((Type) rewrite.createStringPlaceholder(commentToken + typeName, type.getNodeType()));
                resourceCount++;
                if (modifyExistingTry) {
                    resourcesRewriter.insertLast(newVariableDeclarationExpression, null);
                } else {
                    newTryStatement.resources().add(newVariableDeclarationExpression);
                }
                commentToken = null;
            }
        }
    }
    if (resourceCount == 0) {
        return false;
    }
    String label = CorrectionMessages.QuickAssistProcessor_convert_to_try_with_resource;
    LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.QuickFix, context.getCompilationUnit(), rewrite, IProposalRelevance.SURROUND_WITH_TRY_CATCH);
    ImportRewrite imports = proposal.createImportRewrite(context.getASTRoot());
    ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(node, imports);
    CatchClause catchClause = ast.newCatchClause();
    SingleVariableDeclaration decl = ast.newSingleVariableDeclaration();
    String varName = StubUtility.getExceptionVariableName(icu.getJavaProject());
    parentBodyDeclaration.getRoot().accept(analyzer);
    CodeScopeBuilder.Scope scope = CodeScopeBuilder.perform(analyzer.getEnclosingBodyDeclaration(), selection).findScope(selection.getOffset(), selection.getLength());
    scope.setCursor(selection.getOffset());
    String name = scope.createName(varName, false);
    decl.setName(ast.newSimpleName(name));
    List<ITypeBinding> mustRethrowList = new ArrayList<>();
    List<ITypeBinding> catchExceptions = analyzer.calculateCatchesAndRethrows(ASTNodes.filterSubtypes(allExceptions), mustRethrowList);
    List<ITypeBinding> filteredExceptions = ASTNodes.filterSubtypes(catchExceptions);
    if (catchExceptions.size() > 0) {
        // $NON-NLS-1$
        final String GROUP_EXC_NAME = "exc_name";
        // $NON-NLS-1$
        final String GROUP_EXC_TYPE = "exc_type";
        LinkedProposalModelCore linkedProposalModel = new LinkedProposalModelCore();
        int i = 0;
        if (!modifyExistingTry) {
            for (ITypeBinding mustThrow : mustRethrowList) {
                CatchClause newClause = ast.newCatchClause();
                SingleVariableDeclaration newDecl = ast.newSingleVariableDeclaration();
                newDecl.setName(ast.newSimpleName(name));
                Type importType = imports.addImport(mustThrow, ast, importRewriteContext, TypeLocation.EXCEPTION);
                newDecl.setType(importType);
                newClause.setException(newDecl);
                ThrowStatement newThrowStatement = ast.newThrowStatement();
                newThrowStatement.setExpression(ast.newSimpleName(name));
                linkedProposalModel.getPositionGroup(GROUP_EXC_NAME + i, true).addPosition(rewrite.track(decl.getName()), false);
                newClause.getBody().statements().add(newThrowStatement);
                newTryStatement.catchClauses().add(newClause);
                ++i;
            }
        }
        UnionType unionType = ast.newUnionType();
        List<Type> types = unionType.types();
        for (ITypeBinding exception : filteredExceptions) {
            Type type = imports.addImport(exception, ast, importRewriteContext, TypeLocation.EXCEPTION);
            types.add(type);
            linkedProposalModel.getPositionGroup(GROUP_EXC_TYPE + i, true).addPosition(rewrite.track(type), i == 0);
            i++;
        }
        decl.setType(unionType);
        catchClause.setException(decl);
        linkedProposalModel.getPositionGroup(GROUP_EXC_NAME + 0, true).addPosition(rewrite.track(decl.getName()), false);
        Statement st = null;
        // $NON-NLS-1$
        String s = StubUtility.getCatchBodyContent(icu, "Exception", name, coveredNodes.isEmpty() ? node : coveredNodes.get(0), icu.findRecommendedLineSeparator());
        if (s != null) {
            st = (Statement) rewrite.createStringPlaceholder(s, ASTNode.RETURN_STATEMENT);
        }
        if (st != null) {
            catchClause.getBody().statements().add(st);
        }
        if (modifyExistingTry) {
            clausesRewriter.insertLast(catchClause, null);
        } else {
            newTryStatement.catchClauses().add(catchClause);
        }
    }
    if (modifyExistingTry) {
        for (int i = 0; i < coveredAutoClosableNodes.size(); i++) {
            rewrite.remove(coveredAutoClosableNodes.get(i), null);
        }
    } else {
        if (!nodesInRange.isEmpty()) {
            ASTNode firstNode = nodesInRange.get(0);
            ASTNode methodDeclaration = ASTResolving.findAncestor(firstNode, ASTNode.BLOCK);
            ListRewrite listRewrite = rewrite.getListRewrite(methodDeclaration, Block.STATEMENTS_PROPERTY);
            ASTNode createCopyTarget = listRewrite.createMoveTarget(firstNode, nodesInRange.get(nodesInRange.size() - 1));
            rewrite.getListRewrite(newTryBody, Block.STATEMENTS_PROPERTY).insertFirst(createCopyTarget, null);
        }
        // replace first node and delete the rest of selected nodes
        rewrite.replace(coveredAutoClosableNodes.get(0), newTryStatement, null);
        for (int i = 1; i < coveredAutoClosableNodes.size(); i++) {
            rewrite.remove(coveredAutoClosableNodes.get(i), null);
        }
    }
    resultingCollections.add(proposal);
    return true;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) UnionType(org.eclipse.jdt.core.dom.UnionType) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) Selection(org.eclipse.jdt.internal.corext.dom.Selection) SimpleName(org.eclipse.jdt.core.dom.SimpleName) ArrayList(java.util.ArrayList) ListRewrite(org.eclipse.jdt.core.dom.rewrite.ListRewrite) SurroundWithTryWithResourcesAnalyzer(org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesAnalyzer) IBuffer(org.eclipse.jdt.core.IBuffer) TryStatement(org.eclipse.jdt.core.dom.TryStatement) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) VariableDeclarationStatement(org.eclipse.jdt.core.dom.VariableDeclarationStatement) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) ThrowStatement(org.eclipse.jdt.core.dom.ThrowStatement) CodeScopeBuilder(org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) AST(org.eclipse.jdt.core.dom.AST) Statement(org.eclipse.jdt.core.dom.Statement) ThrowStatement(org.eclipse.jdt.core.dom.ThrowStatement) SwitchStatement(org.eclipse.jdt.core.dom.SwitchStatement) ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) TryStatement(org.eclipse.jdt.core.dom.TryStatement) ReturnStatement(org.eclipse.jdt.core.dom.ReturnStatement) VariableDeclarationStatement(org.eclipse.jdt.core.dom.VariableDeclarationStatement) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) CatchClause(org.eclipse.jdt.core.dom.CatchClause) UnionType(org.eclipse.jdt.core.dom.UnionType) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) QualifiedType(org.eclipse.jdt.core.dom.QualifiedType) PrimitiveType(org.eclipse.jdt.core.dom.PrimitiveType) NameQualifiedType(org.eclipse.jdt.core.dom.NameQualifiedType) ArrayType(org.eclipse.jdt.core.dom.ArrayType) SimpleType(org.eclipse.jdt.core.dom.SimpleType) Type(org.eclipse.jdt.core.dom.Type) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) LinkedProposalModelCore(org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore) ImportRewriteContext(org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext) ContextSensitiveImportRewriteContext(org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) ThisExpression(org.eclipse.jdt.core.dom.ThisExpression) Expression(org.eclipse.jdt.core.dom.Expression) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) PostfixExpression(org.eclipse.jdt.core.dom.PostfixExpression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) SwitchExpression(org.eclipse.jdt.core.dom.SwitchExpression) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) Block(org.eclipse.jdt.core.dom.Block) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration)

Example 5 with LinkedCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class QuickAssistProcessor method getConvertMethodReferenceToLambdaProposal.

private static boolean getConvertMethodReferenceToLambdaProposal(IInvocationContext context, ASTNode covering, Collection<ChangeCorrectionProposal> resultingCollections) throws JavaModelException {
    MethodReference methodReference;
    if (covering instanceof MethodReference) {
        methodReference = (MethodReference) covering;
    } else if (covering.getParent() instanceof MethodReference) {
        methodReference = (MethodReference) covering.getParent();
    } else {
        return false;
    }
    IMethodBinding functionalMethod = getFunctionalMethodForMethodReference(methodReference);
    if (functionalMethod == null || functionalMethod.isGenericMethod()) {
        // generic lambda expressions are not allowed
        return false;
    }
    if (resultingCollections == null) {
        return true;
    }
    ASTRewrite rewrite = ASTRewrite.create(methodReference.getAST());
    LinkedProposalModelCore linkedProposalModel = new LinkedProposalModelCore();
    LambdaExpression lambda = convertMethodRefernceToLambda(methodReference, functionalMethod, context.getASTRoot(), rewrite, linkedProposalModel, false);
    // add proposal
    String label = CorrectionMessages.QuickAssistProcessor_convert_to_lambda_expression;
    LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.QuickFix, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_METHOD_REFERENCE_TO_LAMBDA);
    proposal.setLinkedProposalModel(linkedProposalModel);
    proposal.setEndPosition(rewrite.track(lambda));
    resultingCollections.add(proposal);
    return true;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) LinkedProposalModelCore(org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) MethodReference(org.eclipse.jdt.core.dom.MethodReference) TypeMethodReference(org.eclipse.jdt.core.dom.TypeMethodReference) SuperMethodReference(org.eclipse.jdt.core.dom.SuperMethodReference) ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Aggregations

LinkedCorrectionProposal (org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal)8 ASTRewrite (org.eclipse.jdt.core.dom.rewrite.ASTRewrite)7 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)6 AST (org.eclipse.jdt.core.dom.AST)6 ASTNode (org.eclipse.jdt.core.dom.ASTNode)5 BodyDeclaration (org.eclipse.jdt.core.dom.BodyDeclaration)5 CompilationUnit (org.eclipse.jdt.core.dom.CompilationUnit)5 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)5 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)5 PrimitiveType (org.eclipse.jdt.core.dom.PrimitiveType)5 Type (org.eclipse.jdt.core.dom.Type)5 ImportRewrite (org.eclipse.jdt.core.dom.rewrite.ImportRewrite)5 ImportRewriteContext (org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext)5 Expression (org.eclipse.jdt.core.dom.Expression)4 Javadoc (org.eclipse.jdt.core.dom.Javadoc)4 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)4 TagElement (org.eclipse.jdt.core.dom.TagElement)4 TextElement (org.eclipse.jdt.core.dom.TextElement)4 ReturnStatement (org.eclipse.jdt.core.dom.ReturnStatement)3 ContextSensitiveImportRewriteContext (org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext)3