Search in sources :

Example 1 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference in project eclipse.jdt.ls by eclipse.

the class ExceptionAnalyzer method perform.

public static ITypeBinding[] perform(ASTNode enclosingNode, Selection selection) {
    ExceptionAnalyzer analyzer = new ExceptionAnalyzer(enclosingNode, selection);
    enclosingNode.accept(analyzer);
    List<ITypeBinding> exceptions = analyzer.getCurrentExceptions();
    if (enclosingNode.getNodeType() == ASTNode.METHOD_DECLARATION) {
        List<Type> thrownExceptions = ((MethodDeclaration) enclosingNode).thrownExceptionTypes();
        for (Iterator<Type> thrown = thrownExceptions.iterator(); thrown.hasNext(); ) {
            ITypeBinding thrownException = thrown.next().resolveBinding();
            if (thrownException != null) {
                updateExceptionsList(exceptions, thrownException);
            }
        }
    } else {
        ITypeBinding typeBinding = null;
        if (enclosingNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
            typeBinding = ((LambdaExpression) enclosingNode.getParent()).resolveTypeBinding();
        } else if (enclosingNode instanceof MethodReference) {
            typeBinding = ((MethodReference) enclosingNode).resolveTypeBinding();
        }
        if (typeBinding != null) {
            IMethodBinding methodBinding = typeBinding.getFunctionalInterfaceMethod();
            if (methodBinding != null) {
                for (ITypeBinding thrownException : methodBinding.getExceptionTypes()) {
                    updateExceptionsList(exceptions, thrownException);
                }
            }
        }
    }
    Collections.sort(exceptions, new ExceptionComparator());
    return exceptions.toArray(new ITypeBinding[exceptions.size()]);
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) Type(org.eclipse.jdt.core.dom.Type) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) AbstractExceptionAnalyzer(org.eclipse.jdt.ls.core.internal.corext.refactoring.util.AbstractExceptionAnalyzer) MethodReference(org.eclipse.jdt.core.dom.MethodReference) ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference) TypeMethodReference(org.eclipse.jdt.core.dom.TypeMethodReference) SuperMethodReference(org.eclipse.jdt.core.dom.SuperMethodReference)

Example 2 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference in project eclipse.jdt.ls by eclipse.

the class SurroundWithAnalyzer method validSelectedNodes.

private boolean validSelectedNodes() {
    ASTNode[] nodes = getSelectedNodes();
    for (int i = 0; i < nodes.length; i++) {
        ASTNode node = nodes[i];
        boolean isValidNode = node instanceof Statement;
        if (fSurroundWithTryCatch) {
            // allow method reference and lambda's expression body also
            isValidNode = isValidNode || node instanceof MethodReference || node.getLocationInParent() == LambdaExpression.BODY_PROPERTY;
        }
        if (!isValidNode) {
            return false;
        }
    }
    return true;
}
Also used : ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) Statement(org.eclipse.jdt.core.dom.Statement) ASTNode(org.eclipse.jdt.core.dom.ASTNode) MethodReference(org.eclipse.jdt.core.dom.MethodReference)

Example 3 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference in project eclipse.jdt.ls by eclipse.

the class SurroundWithTryCatchRefactoring method createTryCatchStatement.

private void createTryCatchStatement(org.eclipse.jdt.core.IBuffer buffer, String lineDelimiter) throws CoreException {
    List<Statement> result = new ArrayList<>(1);
    TryStatement tryStatement = getAST().newTryStatement();
    ITypeBinding[] exceptions = fAnalyzer.getExceptions();
    ImportRewriteContext context = new ContextSensitiveImportRewriteContext(fAnalyzer.getEnclosingBodyDeclaration(), fImportRewrite);
    if (!fIsMultiCatch) {
        for (int i = 0; i < exceptions.length; i++) {
            ITypeBinding exception = exceptions[i];
            CatchClause catchClause = getAST().newCatchClause();
            tryStatement.catchClauses().add(catchClause);
            SingleVariableDeclaration decl = getAST().newSingleVariableDeclaration();
            String varName = StubUtility.getExceptionVariableName(fCUnit.getJavaProject());
            String name = fScope.createName(varName, false);
            decl.setName(getAST().newSimpleName(name));
            Type type = fImportRewrite.addImport(exception, getAST(), context, TypeLocation.EXCEPTION);
            decl.setType(type);
            catchClause.setException(decl);
            Statement st = getCatchBody(ASTNodes.getQualifiedTypeName(type), name, lineDelimiter);
            if (st != null) {
                catchClause.getBody().statements().add(st);
            }
            fLinkedProposalModel.getPositionGroup(GROUP_EXC_TYPE + i, true).addPosition(fRewriter.track(decl.getType()), i == 0);
            fLinkedProposalModel.getPositionGroup(GROUP_EXC_NAME + i, true).addPosition(fRewriter.track(decl.getName()), false);
        }
    } else {
        List<ITypeBinding> filteredExceptions = filterSubtypeExceptions(exceptions);
        CatchClause catchClause = getAST().newCatchClause();
        SingleVariableDeclaration decl = getAST().newSingleVariableDeclaration();
        String varName = StubUtility.getExceptionVariableName(fCUnit.getJavaProject());
        String name = fScope.createName(varName, false);
        decl.setName(getAST().newSimpleName(name));
        UnionType unionType = getAST().newUnionType();
        List<Type> types = unionType.types();
        int i = 0;
        for (ITypeBinding exception : filteredExceptions) {
            Type type = fImportRewrite.addImport(exception, getAST(), context, TypeLocation.EXCEPTION);
            types.add(type);
            fLinkedProposalModel.getPositionGroup(GROUP_EXC_TYPE + i, true).addPosition(fRewriter.track(type), i == 0);
            i++;
        }
        decl.setType(unionType);
        catchClause.setException(decl);
        fLinkedProposalModel.getPositionGroup(GROUP_EXC_NAME + 0, true).addPosition(fRewriter.track(decl.getName()), false);
        // $NON-NLS-1$
        Statement st = getCatchBody("Exception", name, lineDelimiter);
        if (st != null) {
            catchClause.getBody().statements().add(st);
        }
        tryStatement.catchClauses().add(catchClause);
    }
    List<ASTNode> variableDeclarations = getSpecialVariableDeclarationStatements();
    ListRewrite statements = fRewriter.getListRewrite(tryStatement.getBody(), Block.STATEMENTS_PROPERTY);
    boolean selectedNodeRemoved = false;
    ASTNode expressionStatement = null;
    for (int i = 0; i < fSelectedNodes.length; i++) {
        ASTNode node = fSelectedNodes[i];
        if (node instanceof VariableDeclarationStatement && variableDeclarations.contains(node)) {
            AST ast = getAST();
            VariableDeclarationStatement statement = (VariableDeclarationStatement) node;
            // Create a copy and remove the initializer
            VariableDeclarationStatement copy = (VariableDeclarationStatement) ASTNode.copySubtree(ast, statement);
            List<IExtendedModifier> modifiers = copy.modifiers();
            for (Iterator<IExtendedModifier> iter = modifiers.iterator(); iter.hasNext(); ) {
                IExtendedModifier modifier = iter.next();
                if (modifier.isModifier() && Modifier.isFinal(((Modifier) modifier).getKeyword().toFlagValue())) {
                    iter.remove();
                }
            }
            List<VariableDeclarationFragment> fragments = copy.fragments();
            for (Iterator<VariableDeclarationFragment> iter = fragments.iterator(); iter.hasNext(); ) {
                VariableDeclarationFragment fragment = iter.next();
                fragment.setInitializer(null);
            }
            CompilationUnit root = (CompilationUnit) statement.getRoot();
            int extendedStart = root.getExtendedStartPosition(statement);
            // we have a leading comment and the comment is covered by the selection
            if (extendedStart != statement.getStartPosition() && extendedStart >= fSelection.getOffset()) {
                String commentToken = buffer.getText(extendedStart, statement.getStartPosition() - extendedStart);
                commentToken = Strings.trimTrailingTabsAndSpaces(commentToken);
                Type type = statement.getType();
                String typeName = buffer.getText(type.getStartPosition(), type.getLength());
                copy.setType((Type) fRewriter.createStringPlaceholder(commentToken + typeName, type.getNodeType()));
            }
            result.add(copy);
            // convert the fragments into expression statements
            fragments = statement.fragments();
            if (!fragments.isEmpty()) {
                List<ExpressionStatement> newExpressionStatements = new ArrayList<>();
                for (Iterator<VariableDeclarationFragment> iter = fragments.iterator(); iter.hasNext(); ) {
                    VariableDeclarationFragment fragment = iter.next();
                    Expression initializer = fragment.getInitializer();
                    if (initializer != null) {
                        Assignment assignment = ast.newAssignment();
                        assignment.setLeftHandSide((Expression) fRewriter.createCopyTarget(fragment.getName()));
                        assignment.setRightHandSide((Expression) fRewriter.createCopyTarget(initializer));
                        newExpressionStatements.add(ast.newExpressionStatement(assignment));
                    }
                }
                if (!newExpressionStatements.isEmpty()) {
                    if (fSelectedNodes.length == 1) {
                        expressionStatement = fRewriter.createGroupNode(newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()]));
                    } else {
                        fRewriter.replace(statement, fRewriter.createGroupNode(newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()])), null);
                    }
                } else {
                    fRewriter.remove(statement, null);
                    selectedNodeRemoved = true;
                }
            } else {
                fRewriter.remove(statement, null);
                selectedNodeRemoved = true;
            }
        }
    }
    result.add(tryStatement);
    ASTNode replacementNode;
    if (result.size() == 1) {
        replacementNode = result.get(0);
    } else {
        replacementNode = fRewriter.createGroupNode(result.toArray(new ASTNode[result.size()]));
    }
    if (fSelectedNodes.length == 1) {
        ASTNode selectedNode = fSelectedNodes[0];
        if (selectedNode instanceof MethodReference) {
            MethodReference methodReference = (MethodReference) selectedNode;
            IMethodBinding functionalMethod = QuickAssistProcessor.getFunctionalMethodForMethodReference(methodReference);
            // functionalMethod is non-null and non-generic. See ExceptionAnalyzer.handleMethodReference(MethodReference node).
            Assert.isTrue(functionalMethod != null && !functionalMethod.isGenericMethod());
            LambdaExpression lambda = QuickAssistProcessor.convertMethodRefernceToLambda(methodReference, functionalMethod, fRootNode, fRewriter, null, true);
            ASTNode statementInBlock = (ASTNode) ((Block) lambda.getBody()).statements().get(0);
            fRewriter.replace(statementInBlock, replacementNode, null);
            statements.insertLast(statementInBlock, null);
            return;
        }
        LambdaExpression enclosingLambda = ASTResolving.findEnclosingLambdaExpression(selectedNode);
        if (enclosingLambda != null && selectedNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY && enclosingLambda.resolveMethodBinding() != null) {
            QuickAssistProcessor.changeLambdaBodyToBlock(enclosingLambda, getAST(), fRewriter);
            Block blockBody = (Block) fRewriter.get(enclosingLambda, LambdaExpression.BODY_PROPERTY);
            ASTNode statementInBlock = (ASTNode) blockBody.statements().get(0);
            fRewriter.replace(statementInBlock, replacementNode, null);
            statements.insertLast(statementInBlock, null);
            return;
        }
        if (expressionStatement != null) {
            statements.insertLast(expressionStatement, null);
        } else {
            if (!selectedNodeRemoved) {
                statements.insertLast(fRewriter.createMoveTarget(selectedNode), null);
            }
        }
        fRewriter.replace(selectedNode, replacementNode, null);
    } else {
        ListRewrite source = fRewriter.getListRewrite(fSelectedNodes[0].getParent(), (ChildListPropertyDescriptor) fSelectedNodes[0].getLocationInParent());
        ASTNode toMove = source.createMoveTarget(fSelectedNodes[0], fSelectedNodes[fSelectedNodes.length - 1], replacementNode, null);
        statements.insertLast(toMove, null);
    }
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) UnionType(org.eclipse.jdt.core.dom.UnionType) ArrayList(java.util.ArrayList) ListRewrite(org.eclipse.jdt.core.dom.rewrite.ListRewrite) IExtendedModifier(org.eclipse.jdt.core.dom.IExtendedModifier) Assignment(org.eclipse.jdt.core.dom.Assignment) 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) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) AST(org.eclipse.jdt.core.dom.AST) Statement(org.eclipse.jdt.core.dom.Statement) ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) TryStatement(org.eclipse.jdt.core.dom.TryStatement) VariableDeclarationStatement(org.eclipse.jdt.core.dom.VariableDeclarationStatement) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) CatchClause(org.eclipse.jdt.core.dom.CatchClause) ContextSensitiveImportRewriteContext(org.eclipse.jdt.ls.core.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) UnionType(org.eclipse.jdt.core.dom.UnionType) Type(org.eclipse.jdt.core.dom.Type) ImportRewriteContext(org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext) ContextSensitiveImportRewriteContext(org.eclipse.jdt.ls.core.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) Expression(org.eclipse.jdt.core.dom.Expression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) Block(org.eclipse.jdt.core.dom.Block) MethodReference(org.eclipse.jdt.core.dom.MethodReference) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Example 4 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference in project AutoRefactor by JnRouvignac.

the class ObsoleteRedundantComparatorCleanUp method maybeRefactorTypedCode.

private boolean maybeRefactorTypedCode(final MethodInvocation visitedIfRefactoringNeeded, final Expression list, final Expression comparatorToRemove, final Expression comparatorToAnalyze, final ITypeBinding[] typeArguments, final boolean isForward, final Set<String> classesToUseWithImport, final Set<String> importsToAdd) {
    NullLiteral nullLiteral = ASTNodes.as(comparatorToAnalyze, NullLiteral.class);
    if (nullLiteral != null) {
        return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, isForward, classesToUseWithImport, importsToAdd);
    }
    ClassInstanceCreation classInstanceCreation = ASTNodes.as(comparatorToAnalyze, ClassInstanceCreation.class);
    if (classInstanceCreation != null && isClassToRemove(classInstanceCreation, isForward)) {
        return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, true, classesToUseWithImport, importsToAdd);
    }
    MethodReference methodReference = ASTNodes.as(comparatorToAnalyze, MethodReference.class);
    LambdaExpression lambdaExpression = ASTNodes.as(comparatorToAnalyze, LambdaExpression.class);
    MethodInvocation methodInvocation = ASTNodes.as(comparatorToAnalyze, MethodInvocation.class);
    if (methodReference != null) {
        String elementClass = typeArguments[0].isWildcardType() ? Comparable.class.getCanonicalName() : typeArguments[0].getQualifiedName();
        if (// $NON-NLS-1$
        ASTNodes.usesGivenSignature(// $NON-NLS-1$
        methodReference.resolveMethodBinding(), // $NON-NLS-1$
        elementClass, // $NON-NLS-1$
        "compareTo", Object.class.getCanonicalName())) {
            return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, isForward, classesToUseWithImport, importsToAdd);
        }
    } else if (methodInvocation != null) {
        if (// $NON-NLS-1$
        ASTNodes.usesGivenSignature(methodInvocation, Comparator.class.getCanonicalName(), "reversed") && methodInvocation.getExpression() != null) {
            return maybeRefactorTypedCode(visitedIfRefactoringNeeded, list, comparatorToRemove, methodInvocation.getExpression(), typeArguments, !isForward, classesToUseWithImport, importsToAdd);
        }
        if (ASTNodes.usesGivenSignature(methodInvocation, Comparator.class.getCanonicalName(), "naturalOrder")) {
            // $NON-NLS-1$
            return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, isForward, classesToUseWithImport, importsToAdd);
        }
        if (// $NON-NLS-1$
        "comparing".equals(methodInvocation.getName().getIdentifier()) && methodInvocation.resolveMethodBinding() != null && methodInvocation.resolveMethodBinding().getParameterTypes().length == 1 && ASTNodes.hasType(methodInvocation.resolveMethodBinding().getDeclaringClass(), Comparator.class.getCanonicalName()) && ASTNodes.hasType(methodInvocation.resolveMethodBinding().getParameterTypes()[0], Function.class.getCanonicalName())) {
            List<Expression> comparingMethodArgs = methodInvocation.arguments();
            Expression criteria = comparingMethodArgs.get(0);
            LambdaExpression comparingMethodLambdaExpression = ASTNodes.as(criteria, LambdaExpression.class);
            MethodInvocation identityMethod = ASTNodes.as(criteria, MethodInvocation.class);
            if (comparingMethodLambdaExpression != null) {
                if (comparingMethodLambdaExpression.parameters().size() == 1) {
                    List<VariableDeclaration> parameters = comparingMethodLambdaExpression.parameters();
                    SimpleName variable = parameters.get(0).getName();
                    Expression bodyExpression = null;
                    if (comparingMethodLambdaExpression.getBody() instanceof Block) {
                        ReturnStatement returnStatement = ASTNodes.as((Block) comparingMethodLambdaExpression.getBody(), ReturnStatement.class);
                        if (returnStatement == null) {
                            return true;
                        }
                        bodyExpression = returnStatement.getExpression();
                    } else if (comparingMethodLambdaExpression.getBody() instanceof Expression) {
                        bodyExpression = (Expression) comparingMethodLambdaExpression.getBody();
                    } else {
                        return true;
                    }
                    if (ASTNodes.areSameVariables(variable, bodyExpression)) {
                        return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, isForward, classesToUseWithImport, importsToAdd);
                    }
                }
            } else if (identityMethod != null && // $NON-NLS-1$
            "identity".equals(identityMethod.getName().getIdentifier()) && identityMethod.resolveMethodBinding() != null && identityMethod.resolveMethodBinding().getParameterTypes().length == 0 && ASTNodes.hasType(identityMethod.resolveMethodBinding().getDeclaringClass(), Function.class.getCanonicalName())) {
                return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, isForward, classesToUseWithImport, importsToAdd);
            }
        }
    } else if (lambdaExpression != null) {
        if (lambdaExpression.parameters().size() == 2) {
            List<ASTNode> parameters = lambdaExpression.parameters();
            ASTNode parameter1 = parameters.get(0);
            ASTNode parameter2 = parameters.get(1);
            SimpleName variable1;
            if (parameter1 instanceof SingleVariableDeclaration) {
                variable1 = ((SingleVariableDeclaration) parameter1).getName();
            } else if (parameter1 instanceof VariableDeclarationFragment) {
                variable1 = ((VariableDeclarationFragment) parameter1).getName();
            } else {
                return true;
            }
            SimpleName variable2;
            if (parameter2 instanceof SingleVariableDeclaration) {
                variable2 = ((SingleVariableDeclaration) parameter2).getName();
            } else if (parameter2 instanceof VariableDeclarationFragment) {
                variable2 = ((VariableDeclarationFragment) parameter2).getName();
            } else {
                return true;
            }
            Expression bodyExpression = null;
            if (lambdaExpression.getBody() instanceof Block) {
                ReturnStatement returnStatement = ASTNodes.as((Block) lambdaExpression.getBody(), ReturnStatement.class);
                if (returnStatement == null) {
                    return true;
                }
                bodyExpression = returnStatement.getExpression();
            } else if (lambdaExpression.getBody() instanceof Expression) {
                bodyExpression = (Expression) lambdaExpression.getBody();
            } else {
                return true;
            }
            if (isReturnedExpressionToRemove(variable1, variable2, bodyExpression, isForward)) {
                return maybeRemoveComparator(visitedIfRefactoringNeeded, list, comparatorToRemove, true, classesToUseWithImport, importsToAdd);
            }
        }
    }
    return true;
}
Also used : ClassInstanceCreation(org.eclipse.jdt.core.dom.ClassInstanceCreation) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) SimpleName(org.eclipse.jdt.core.dom.SimpleName) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) Comparator(java.util.Comparator) Function(java.util.function.Function) Expression(org.eclipse.jdt.core.dom.Expression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) ReturnStatement(org.eclipse.jdt.core.dom.ReturnStatement) ASTNode(org.eclipse.jdt.core.dom.ASTNode) Block(org.eclipse.jdt.core.dom.Block) MethodReference(org.eclipse.jdt.core.dom.MethodReference) List(java.util.List) NullLiteral(org.eclipse.jdt.core.dom.NullLiteral) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Example 5 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference in project eclipse.jdt.ls by eclipse.

the class LocalCorrectionsSubProcessor method addUncaughtExceptionProposals.

public static void addUncaughtExceptionProposals(IInvocationContext context, IProblemLocation problem, Collection<CUCorrectionProposal> proposals) throws CoreException {
    ICompilationUnit cu = context.getCompilationUnit();
    CompilationUnit astRoot = context.getASTRoot();
    ASTNode selectedNode = problem.getCoveringNode(astRoot);
    if (selectedNode == null) {
        return;
    }
    while (selectedNode != null && !(selectedNode instanceof Statement) && !(selectedNode instanceof VariableDeclarationExpression) && !(selectedNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY) && !(selectedNode instanceof MethodReference)) {
        selectedNode = selectedNode.getParent();
    }
    if (selectedNode == null) {
        return;
    }
    int offset = selectedNode.getStartPosition();
    int length = selectedNode.getLength();
    int selectionEnd = context.getSelectionOffset() + context.getSelectionLength();
    if (selectionEnd > offset + length) {
        // extend the selection if more than one statement is selected (bug 72149)
        length = selectionEnd - offset;
    }
    // Surround with proposals
    SurroundWithTryCatchRefactoring refactoring = SurroundWithTryCatchRefactoring.create(cu, offset, length);
    if (refactoring == null) {
        return;
    }
    refactoring.setLeaveDirty(true);
    if (refactoring.checkActivationBasics(astRoot).isOK()) {
        String label = CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trycatch_description;
        RefactoringCorrectionProposal proposal = new RefactoringCorrectionProposal(label, cu, refactoring, IProposalRelevance.SURROUND_WITH_TRY_CATCH);
        proposal.setLinkedProposalModel(refactoring.getLinkedProposalModel());
        proposals.add(proposal);
    }
    if (JavaModelUtil.is17OrHigher(cu.getJavaProject())) {
        refactoring = SurroundWithTryCatchRefactoring.create(cu, offset, length, true);
        if (refactoring == null) {
            return;
        }
        refactoring.setLeaveDirty(true);
        if (refactoring.checkActivationBasics(astRoot).isOK()) {
            String label = CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trymulticatch_description;
            RefactoringCorrectionProposal proposal = new RefactoringCorrectionProposal(label, cu, refactoring, IProposalRelevance.SURROUND_WITH_TRY_MULTICATCH);
            proposal.setLinkedProposalModel(refactoring.getLinkedProposalModel());
            proposals.add(proposal);
        }
    }
    // Catch exception
    BodyDeclaration decl = ASTResolving.findParentBodyDeclaration(selectedNode);
    if (decl == null) {
        return;
    }
    ASTNode enclosingNode = SurroundWithAnalyzer.getEnclosingNode(selectedNode);
    if (enclosingNode == null) {
        return;
    }
    ITypeBinding[] uncaughtExceptions = ExceptionAnalyzer.perform(enclosingNode, Selection.createFromStartLength(offset, length));
    if (uncaughtExceptions.length == 0) {
        return;
    }
    TryStatement surroundingTry = ASTResolving.findParentTryStatement(selectedNode);
    AST ast = astRoot.getAST();
    if (surroundingTry != null && (ASTNodes.isParent(selectedNode, surroundingTry.getBody()) || selectedNode.getLocationInParent() == TryStatement.RESOURCES_PROPERTY)) {
        {
            ASTRewrite rewrite = ASTRewrite.create(surroundingTry.getAST());
            String label = CorrectionMessages.LocalCorrectionsSubProcessor_addadditionalcatch_description;
            LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_ADDITIONAL_CATCH);
            ImportRewrite imports = proposal.createImportRewrite(context.getASTRoot());
            ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(decl, imports);
            CodeScopeBuilder.Scope scope = CodeScopeBuilder.perform(decl, Selection.createFromStartLength(offset, length)).findScope(offset, length);
            scope.setCursor(offset);
            ListRewrite clausesRewrite = rewrite.getListRewrite(surroundingTry, TryStatement.CATCH_CLAUSES_PROPERTY);
            for (int i = 0; i < uncaughtExceptions.length; i++) {
                ITypeBinding excBinding = uncaughtExceptions[i];
                String varName = StubUtility.getExceptionVariableName(cu.getJavaProject());
                String name = scope.createName(varName, false);
                SingleVariableDeclaration var = ast.newSingleVariableDeclaration();
                var.setName(ast.newSimpleName(name));
                var.setType(imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION));
                CatchClause newClause = ast.newCatchClause();
                newClause.setException(var);
                String catchBody = StubUtility.getCatchBodyContent(cu, excBinding.getName(), name, selectedNode, String.valueOf('\n'));
                if (catchBody != null) {
                    ASTNode node = rewrite.createStringPlaceholder(catchBody, ASTNode.RETURN_STATEMENT);
                    newClause.getBody().statements().add(node);
                }
                clausesRewrite.insertLast(newClause, null);
                // $NON-NLS-1$
                String typeKey = "type" + i;
                // $NON-NLS-1$
                String nameKey = "name" + i;
                proposal.addLinkedPosition(rewrite.track(var.getType()), false, typeKey);
                proposal.addLinkedPosition(rewrite.track(var.getName()), false, nameKey);
                addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
            }
            proposals.add(proposal);
        }
        if (JavaModelUtil.is17OrHigher(cu.getJavaProject())) {
            List<CatchClause> catchClauses = surroundingTry.catchClauses();
            if (catchClauses != null && catchClauses.size() == 1) {
                List<ITypeBinding> filteredExceptions = SurroundWithTryCatchRefactoring.filterSubtypeExceptions(uncaughtExceptions);
                String label = filteredExceptions.size() > 1 ? CorrectionMessages.LocalCorrectionsSubProcessor_addexceptionstoexistingcatch_description : CorrectionMessages.LocalCorrectionsSubProcessor_addexceptiontoexistingcatch_description;
                ASTRewrite rewrite = ASTRewrite.create(ast);
                LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_EXCEPTIONS_TO_EXISTING_CATCH);
                ImportRewrite imports = proposal.createImportRewrite(context.getASTRoot());
                ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(decl, imports);
                CatchClause catchClause = catchClauses.get(0);
                Type type = catchClause.getException().getType();
                if (type instanceof UnionType) {
                    UnionType unionType = (UnionType) type;
                    ListRewrite listRewrite = rewrite.getListRewrite(unionType, UnionType.TYPES_PROPERTY);
                    for (int i = 0; i < filteredExceptions.size(); i++) {
                        ITypeBinding excBinding = filteredExceptions.get(i);
                        Type type2 = imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION);
                        listRewrite.insertLast(type2, null);
                        // $NON-NLS-1$
                        String typeKey = "type" + i;
                        proposal.addLinkedPosition(rewrite.track(type2), false, typeKey);
                        addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
                    }
                } else {
                    UnionType newUnionType = ast.newUnionType();
                    List<Type> types = newUnionType.types();
                    types.add((Type) rewrite.createCopyTarget(type));
                    for (int i = 0; i < filteredExceptions.size(); i++) {
                        ITypeBinding excBinding = filteredExceptions.get(i);
                        Type type2 = imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION);
                        types.add(type2);
                        // $NON-NLS-1$
                        String typeKey = "type" + i;
                        proposal.addLinkedPosition(rewrite.track(type2), false, typeKey);
                        addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
                    }
                    rewrite.replace(type, newUnionType, null);
                }
                proposals.add(proposal);
            } else if (catchClauses != null && catchClauses.size() == 0) {
                List<ITypeBinding> filteredExceptions = SurroundWithTryCatchRefactoring.filterSubtypeExceptions(uncaughtExceptions);
                if (filteredExceptions.size() > 1) {
                    String label = CorrectionMessages.LocalCorrectionsSubProcessor_addadditionalmulticatch_description;
                    ASTRewrite rewrite = ASTRewrite.create(ast);
                    LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_ADDITIONAL_MULTI_CATCH);
                    ImportRewrite imports = proposal.createImportRewrite(context.getASTRoot());
                    ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(decl, imports);
                    CodeScopeBuilder.Scope scope = CodeScopeBuilder.perform(decl, Selection.createFromStartLength(offset, length)).findScope(offset, length);
                    scope.setCursor(offset);
                    CatchClause newCatchClause = ast.newCatchClause();
                    String varName = StubUtility.getExceptionVariableName(cu.getJavaProject());
                    String name = scope.createName(varName, false);
                    SingleVariableDeclaration var = ast.newSingleVariableDeclaration();
                    var.setName(ast.newSimpleName(name));
                    UnionType newUnionType = ast.newUnionType();
                    List<Type> types = newUnionType.types();
                    for (int i = 0; i < filteredExceptions.size(); i++) {
                        ITypeBinding excBinding = filteredExceptions.get(i);
                        Type type2 = imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION);
                        types.add(type2);
                        // $NON-NLS-1$
                        String typeKey = "type" + i;
                        proposal.addLinkedPosition(rewrite.track(type2), false, typeKey);
                        addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
                    }
                    // $NON-NLS-1$
                    String nameKey = "name";
                    proposal.addLinkedPosition(rewrite.track(var.getName()), false, nameKey);
                    var.setType(newUnionType);
                    newCatchClause.setException(var);
                    // $NON-NLS-1$
                    String catchBody = StubUtility.getCatchBodyContent(cu, "Exception", name, selectedNode, String.valueOf('\n'));
                    if (catchBody != null) {
                        ASTNode node = rewrite.createStringPlaceholder(catchBody, ASTNode.RETURN_STATEMENT);
                        newCatchClause.getBody().statements().add(node);
                    }
                    ListRewrite listRewrite = rewrite.getListRewrite(surroundingTry, TryStatement.CATCH_CLAUSES_PROPERTY);
                    listRewrite.insertFirst(newCatchClause, null);
                    proposals.add(proposal);
                }
            }
        }
    }
    // Add throws declaration
    if (enclosingNode instanceof MethodDeclaration) {
        MethodDeclaration methodDecl = (MethodDeclaration) enclosingNode;
        IMethodBinding binding = methodDecl.resolveBinding();
        boolean isApplicable = (binding != null);
        if (isApplicable) {
            IMethodBinding overriddenMethod = Bindings.findOverriddenMethod(binding, true);
            if (overriddenMethod != null) {
                isApplicable = overriddenMethod.getDeclaringClass().isFromSource();
                if (!isApplicable) {
                    // bug 349051
                    ITypeBinding[] exceptionTypes = overriddenMethod.getExceptionTypes();
                    ArrayList<ITypeBinding> unhandledExceptions = new ArrayList<>(uncaughtExceptions.length);
                    for (int i = 0; i < uncaughtExceptions.length; i++) {
                        ITypeBinding curr = uncaughtExceptions[i];
                        if (isSubtype(curr, exceptionTypes)) {
                            unhandledExceptions.add(curr);
                        }
                    }
                    uncaughtExceptions = unhandledExceptions.toArray(new ITypeBinding[unhandledExceptions.size()]);
                    isApplicable |= uncaughtExceptions.length > 0;
                }
            }
        }
        if (isApplicable) {
            ITypeBinding[] methodExceptions = binding.getExceptionTypes();
            ArrayList<ITypeBinding> unhandledExceptions = new ArrayList<>(uncaughtExceptions.length);
            for (int i = 0; i < uncaughtExceptions.length; i++) {
                ITypeBinding curr = uncaughtExceptions[i];
                if (!isSubtype(curr, methodExceptions)) {
                    unhandledExceptions.add(curr);
                }
            }
            uncaughtExceptions = unhandledExceptions.toArray(new ITypeBinding[unhandledExceptions.size()]);
            List<Type> exceptions = methodDecl.thrownExceptionTypes();
            int nExistingExceptions = exceptions.size();
            ChangeDescription[] desc = new ChangeDescription[nExistingExceptions + uncaughtExceptions.length];
            for (int i = 0; i < exceptions.size(); i++) {
                Type elem = exceptions.get(i);
                if (isSubtype(elem.resolveBinding(), uncaughtExceptions)) {
                    desc[i] = new RemoveDescription();
                }
            }
            for (int i = 0; i < uncaughtExceptions.length; i++) {
                // $NON-NLS-1$
                desc[i + nExistingExceptions] = new InsertDescription(uncaughtExceptions[i], "");
            }
            String label = CorrectionMessages.LocalCorrectionsSubProcessor_addthrows_description;
            ChangeMethodSignatureProposal proposal = new ChangeMethodSignatureProposal(label, cu, astRoot, binding, null, desc, IProposalRelevance.ADD_THROWS_DECLARATION);
            for (int i = 0; i < uncaughtExceptions.length; i++) {
                addExceptionTypeLinkProposals(proposal, uncaughtExceptions[i], proposal.getExceptionTypeGroupId(i + nExistingExceptions));
            }
            proposals.add(proposal);
        }
    }
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) UnionType(org.eclipse.jdt.core.dom.UnionType) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) InsertDescription(org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.InsertDescription) ArrayList(java.util.ArrayList) ListRewrite(org.eclipse.jdt.core.dom.rewrite.ListRewrite) SurroundWithTryCatchRefactoring(org.eclipse.jdt.ls.core.internal.corext.refactoring.surround.SurroundWithTryCatchRefactoring) TryStatement(org.eclipse.jdt.core.dom.TryStatement) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ChangeDescription(org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.ChangeDescription) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) List(java.util.List) ArrayList(java.util.ArrayList) RemoveDescription(org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.RemoveDescription) 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) Statement(org.eclipse.jdt.core.dom.Statement) ExpressionStatement(org.eclipse.jdt.core.dom.ExpressionStatement) TryStatement(org.eclipse.jdt.core.dom.TryStatement) SwitchStatement(org.eclipse.jdt.core.dom.SwitchStatement) IfStatement(org.eclipse.jdt.core.dom.IfStatement) WhileStatement(org.eclipse.jdt.core.dom.WhileStatement) ForStatement(org.eclipse.jdt.core.dom.ForStatement) EmptyStatement(org.eclipse.jdt.core.dom.EmptyStatement) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) CatchClause(org.eclipse.jdt.core.dom.CatchClause) ContextSensitiveImportRewriteContext(org.eclipse.jdt.ls.core.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) UnionType(org.eclipse.jdt.core.dom.UnionType) Type(org.eclipse.jdt.core.dom.Type) ImportRewriteContext(org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext) ContextSensitiveImportRewriteContext(org.eclipse.jdt.ls.core.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext) MethodReference(org.eclipse.jdt.core.dom.MethodReference) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration)

Aggregations

MethodReference (org.eclipse.jdt.core.dom.MethodReference)7 ASTNode (org.eclipse.jdt.core.dom.ASTNode)6 Block (org.eclipse.jdt.core.dom.Block)3 ExpressionStatement (org.eclipse.jdt.core.dom.ExpressionStatement)3 IMethodBinding (org.eclipse.jdt.core.dom.IMethodBinding)3 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)3 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)3 SingleVariableDeclaration (org.eclipse.jdt.core.dom.SingleVariableDeclaration)3 Statement (org.eclipse.jdt.core.dom.Statement)3 Type (org.eclipse.jdt.core.dom.Type)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)2 AST (org.eclipse.jdt.core.dom.AST)2 CatchClause (org.eclipse.jdt.core.dom.CatchClause)2 CompilationUnit (org.eclipse.jdt.core.dom.CompilationUnit)2 Expression (org.eclipse.jdt.core.dom.Expression)2 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)2 TryStatement (org.eclipse.jdt.core.dom.TryStatement)2 UnionType (org.eclipse.jdt.core.dom.UnionType)2