Search in sources :

Example 6 with MethodReference

use of org.eclipse.jdt.core.dom.MethodReference 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)

Example 7 with MethodReference

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

the class QuickAssistProcessor method getConvertLambdaToMethodReferenceProposal.

private static boolean getConvertLambdaToMethodReferenceProposal(IInvocationContext context, ASTNode coveringNode, Collection<ChangeCorrectionProposal> resultingCollections) {
    LambdaExpression lambda;
    if (coveringNode instanceof LambdaExpression) {
        lambda = (LambdaExpression) coveringNode;
    } else if (coveringNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
        lambda = (LambdaExpression) coveringNode.getParent();
    } else {
        lambda = ASTResolving.findEnclosingLambdaExpression(coveringNode);
        if (lambda == null) {
            return false;
        }
    }
    ASTNode lambdaBody = lambda.getBody();
    Expression exprBody;
    if (lambdaBody instanceof Block) {
        exprBody = getSingleExpressionFromLambdaBody((Block) lambdaBody);
    } else {
        exprBody = (Expression) lambdaBody;
    }
    exprBody = ASTNodes.getUnparenthesedExpression(exprBody);
    if (exprBody == null || !isValidLambdaReferenceToMethod(exprBody)) {
        return false;
    }
    if (!ASTNodes.isParent(exprBody, coveringNode) && !representsDefiningNode(coveringNode, exprBody)) {
        return false;
    }
    List<Expression> lambdaParameters = new ArrayList<>();
    for (VariableDeclaration param : (List<VariableDeclaration>) lambda.parameters()) {
        lambdaParameters.add(param.getName());
    }
    if (exprBody instanceof ClassInstanceCreation) {
        ClassInstanceCreation cic = (ClassInstanceCreation) exprBody;
        if (cic.getExpression() != null || cic.getAnonymousClassDeclaration() != null) {
            return false;
        }
        if (!matches(lambdaParameters, cic.arguments())) {
            return false;
        }
    } else if (exprBody instanceof ArrayCreation) {
        List<Expression> dimensions = ((ArrayCreation) exprBody).dimensions();
        if (dimensions.size() != 1) {
            return false;
        }
        if (!matches(lambdaParameters, dimensions)) {
            return false;
        }
    } else if (exprBody instanceof SuperMethodInvocation) {
        SuperMethodInvocation superMethodInvocation = (SuperMethodInvocation) exprBody;
        IMethodBinding methodBinding = superMethodInvocation.resolveMethodBinding();
        if (methodBinding == null) {
            return false;
        }
        if (Modifier.isStatic(methodBinding.getModifiers())) {
            ITypeBinding invocationTypeBinding = ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superMethodInvocation.getQualifier());
            if (invocationTypeBinding == null) {
                return false;
            }
        }
        if (!matches(lambdaParameters, superMethodInvocation.arguments())) {
            return false;
        }
    } else {
        // MethodInvocation
        MethodInvocation methodInvocation = (MethodInvocation) exprBody;
        IMethodBinding methodBinding = methodInvocation.resolveMethodBinding();
        if (methodBinding == null) {
            return false;
        }
        Expression invocationExpr = methodInvocation.getExpression();
        if (Modifier.isStatic(methodBinding.getModifiers())) {
            ITypeBinding invocationTypeBinding = ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationExpr);
            if (invocationTypeBinding == null) {
                return false;
            }
            if (!matches(lambdaParameters, methodInvocation.arguments())) {
                return false;
            }
        } else if ((lambda.parameters().size() - methodInvocation.arguments().size()) == 1) {
            if (invocationExpr == null) {
                return false;
            }
            ITypeBinding invocationTypeBinding = invocationExpr.resolveTypeBinding();
            if (invocationTypeBinding == null) {
                return false;
            }
            IMethodBinding lambdaMethodBinding = lambda.resolveMethodBinding();
            if (lambdaMethodBinding == null) {
                return false;
            }
            ITypeBinding firstParamType = lambdaMethodBinding.getParameterTypes()[0];
            if ((!Bindings.equals(invocationTypeBinding, firstParamType) && !Bindings.isSuperType(invocationTypeBinding, firstParamType)) || !JdtASTMatcher.doNodesMatch(lambdaParameters.get(0), invocationExpr) || !matches(lambdaParameters.subList(1, lambdaParameters.size()), methodInvocation.arguments())) {
                return false;
            }
        } else if (!matches(lambdaParameters, methodInvocation.arguments())) {
            return false;
        }
    }
    if (resultingCollections == null) {
        return true;
    }
    AST ast = lambda.getAST();
    ASTRewrite rewrite = ASTRewrite.create(ast);
    ImportRewrite importRewrite = null;
    MethodReference replacement;
    if (exprBody instanceof ClassInstanceCreation) {
        CreationReference creationReference = ast.newCreationReference();
        replacement = creationReference;
        ClassInstanceCreation cic = (ClassInstanceCreation) exprBody;
        Type type = cic.getType();
        if (type.isParameterizedType() && ((ParameterizedType) type).typeArguments().size() == 0) {
            type = ((ParameterizedType) type).getType();
        }
        creationReference.setType((Type) rewrite.createCopyTarget(type));
        creationReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, cic.typeArguments()));
    } else if (exprBody instanceof ArrayCreation) {
        CreationReference creationReference = ast.newCreationReference();
        replacement = creationReference;
        ArrayType arrayType = ((ArrayCreation) exprBody).getType();
        Type copiedElementType = (Type) rewrite.createCopyTarget(arrayType.getElementType());
        creationReference.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions()));
    } else if (exprBody instanceof SuperMethodInvocation) {
        SuperMethodInvocation superMethodInvocation = (SuperMethodInvocation) exprBody;
        IMethodBinding methodBinding = superMethodInvocation.resolveMethodBinding();
        Name superQualifier = superMethodInvocation.getQualifier();
        if (Modifier.isStatic(methodBinding.getModifiers())) {
            TypeMethodReference typeMethodReference = ast.newTypeMethodReference();
            replacement = typeMethodReference;
            typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName()));
            importRewrite = StubUtility.createImportRewrite(context.getASTRoot(), true);
            ITypeBinding invocationTypeBinding = ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superQualifier);
            typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding.getTypeDeclaration(), ast));
            typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments()));
        } else {
            SuperMethodReference superMethodReference = ast.newSuperMethodReference();
            replacement = superMethodReference;
            if (superQualifier != null) {
                superMethodReference.setQualifier((Name) rewrite.createCopyTarget(superQualifier));
            }
            superMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName()));
            superMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments()));
        }
    } else {
        // MethodInvocation
        MethodInvocation methodInvocation = (MethodInvocation) exprBody;
        IMethodBinding methodBinding = methodInvocation.resolveMethodBinding();
        Expression invocationQualifier = methodInvocation.getExpression();
        boolean isStaticMethod = Modifier.isStatic(methodBinding.getModifiers());
        boolean isTypeRefToInstanceMethod = methodInvocation.arguments().size() != lambda.parameters().size();
        if (isStaticMethod || isTypeRefToInstanceMethod) {
            TypeMethodReference typeMethodReference = ast.newTypeMethodReference();
            replacement = typeMethodReference;
            typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
            importRewrite = StubUtility.createImportRewrite(context.getASTRoot(), true);
            ITypeBinding invocationTypeBinding = ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationQualifier);
            invocationTypeBinding = StubUtility2Core.replaceWildcardsAndCaptures(invocationTypeBinding);
            ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(lambda, importRewrite);
            typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding, ast, importRewriteContext, TypeLocation.OTHER));
            typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments()));
        } else {
            ExpressionMethodReference exprMethodReference = ast.newExpressionMethodReference();
            replacement = exprMethodReference;
            exprMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
            if (invocationQualifier != null) {
                exprMethodReference.setExpression((Expression) rewrite.createCopyTarget(invocationQualifier));
            } else {
                // check if method is in class scope or in super/nested class scope
                TypeDeclaration lambdaParentType = (TypeDeclaration) ASTResolving.findParentType(lambda);
                ITypeBinding lambdaMethodInvokingClass = lambdaParentType.resolveBinding();
                ITypeBinding lambdaMethodDeclaringClass = methodBinding.getDeclaringClass();
                ThisExpression newThisExpression = ast.newThisExpression();
                ITypeBinding nestedRootClass = getNestedRootClass(lambdaMethodInvokingClass);
                boolean isSuperClass = isSuperClass(lambdaMethodDeclaringClass, lambdaMethodInvokingClass);
                boolean isNestedClass = isNestedClass(lambdaMethodDeclaringClass, lambdaMethodInvokingClass);
                if (lambdaMethodDeclaringClass == lambdaMethodInvokingClass) {
                // use this::
                } else if (Modifier.isDefault(methodBinding.getModifiers())) {
                    boolean nestedInterfaceClass = isNestedInterfaceClass(ast, lambdaMethodDeclaringClass, lambdaMethodInvokingClass);
                    if (isNestedClass) {
                    // use this::
                    } else if (nestedInterfaceClass && !isNestedClass && !isSuperClass) {
                    // use this::
                    } else if (!nestedInterfaceClass || (nestedRootClass != lambdaMethodInvokingClass)) {
                        newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
                    }
                } else if (lambdaMethodDeclaringClass.isInterface()) {
                    if (isSuperClass) {
                    // use this::
                    } else {
                        newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
                    }
                } else if (isSuperClass) {
                // use this::
                } else {
                    newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
                }
                exprMethodReference.setExpression(newThisExpression);
            }
            exprMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments()));
        }
    }
    rewrite.replace(lambda, replacement, null);
    // add correction proposal
    String label = CorrectionMessages.QuickAssistProcessor_convert_to_method_reference;
    ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, CodeActionKind.QuickFix, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_TO_METHOD_REFERENCE);
    if (importRewrite != null) {
        proposal.setImportRewrite(importRewrite);
    }
    resultingCollections.add(proposal);
    return true;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) ArrayList(java.util.ArrayList) CreationReference(org.eclipse.jdt.core.dom.CreationReference) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) SuperMethodInvocation(org.eclipse.jdt.core.dom.SuperMethodInvocation) SuperMethodInvocation(org.eclipse.jdt.core.dom.SuperMethodInvocation) SimpleName(org.eclipse.jdt.core.dom.SimpleName) Name(org.eclipse.jdt.core.dom.Name) ArrayType(org.eclipse.jdt.core.dom.ArrayType) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) ThisExpression(org.eclipse.jdt.core.dom.ThisExpression) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) VariableDeclaration(org.eclipse.jdt.core.dom.VariableDeclaration) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) ArrayList(java.util.ArrayList) List(java.util.List) TypeMethodReference(org.eclipse.jdt.core.dom.TypeMethodReference) SuperMethodReference(org.eclipse.jdt.core.dom.SuperMethodReference) ClassInstanceCreation(org.eclipse.jdt.core.dom.ClassInstanceCreation) AST(org.eclipse.jdt.core.dom.AST) ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference) 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) 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) ArrayCreation(org.eclipse.jdt.core.dom.ArrayCreation) Block(org.eclipse.jdt.core.dom.Block) 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) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration)

Example 8 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)

Example 9 with MethodReference

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

the class SurroundWithAnalyzer method endVisit.

@Override
public void endVisit(CompilationUnit node) {
    postProcessSelectedNodes(internalGetSelectedNodes());
    ASTNode enclosingNode = null;
    superCall: {
        if (getStatus().hasFatalError()) {
            break superCall;
        }
        if (!hasSelectedNodes()) {
            ASTNode coveringNode = getLastCoveringNode();
            if (coveringNode instanceof Block) {
                Block block = (Block) coveringNode;
                Message[] messages = ASTNodes.getMessages(block, ASTNodes.NODE_ONLY);
                if (messages.length > 0) {
                    invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_compile_errors, JavaStatusContext.create(getCompilationUnit(), block));
                    break superCall;
                }
            }
            invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_doesNotCover);
            break superCall;
        }
        enclosingNode = getEnclosingNode(getFirstSelectedNode());
        boolean isValidEnclosingNode = enclosingNode instanceof MethodDeclaration || enclosingNode instanceof Initializer;
        if (fSurroundWithTryCatch) {
            isValidEnclosingNode = isValidEnclosingNode || enclosingNode instanceof MethodReference || enclosingNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY;
        }
        if (!isValidEnclosingNode) {
            invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_doesNotContain);
            break superCall;
        }
        if (!validSelectedNodes()) {
            invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_onlyStatements);
        }
        fLocals = LocalDeclarationAnalyzer.perform(enclosingNode, getSelection());
    }
    super.endVisit(node);
}
Also used : Message(org.eclipse.jdt.core.dom.Message) Initializer(org.eclipse.jdt.core.dom.Initializer) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) ASTNode(org.eclipse.jdt.core.dom.ASTNode) Block(org.eclipse.jdt.core.dom.Block) MethodReference(org.eclipse.jdt.core.dom.MethodReference)

Example 10 with MethodReference

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

the class RefactorProcessor method getConvertResolvedTypeToVarTypeProposal.

private static boolean getConvertResolvedTypeToVarTypeProposal(IInvocationContext context, ASTNode node, Collection<ChangeCorrectionProposal> proposals) {
    CompilationUnit astRoot = context.getASTRoot();
    IJavaElement root = astRoot.getJavaElement();
    if (root == null) {
        return false;
    }
    IJavaProject javaProject = root.getJavaProject();
    if (javaProject == null) {
        return false;
    }
    if (!JavaModelUtil.is10OrHigher(javaProject)) {
        return false;
    }
    SimpleName name = getSimpleNameForVariable(node);
    if (name == null) {
        return false;
    }
    IBinding binding = name.resolveBinding();
    if (!(binding instanceof IVariableBinding)) {
        return false;
    }
    IVariableBinding varBinding = (IVariableBinding) binding;
    if (varBinding.isField() || varBinding.isParameter()) {
        return false;
    }
    ASTNode varDeclaration = astRoot.findDeclaringNode(varBinding);
    if (varDeclaration == null) {
        return false;
    }
    Type type = null;
    Expression expression = null;
    ITypeBinding typeBinding = varBinding.getType();
    if (typeBinding == null) {
        return false;
    }
    ITypeBinding expressionTypeBinding = null;
    if (varDeclaration instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration svDecl = (SingleVariableDeclaration) varDeclaration;
        type = svDecl.getType();
        expression = svDecl.getInitializer();
        if (expression != null) {
            expressionTypeBinding = expression.resolveTypeBinding();
        } else {
            ASTNode parent = svDecl.getParent();
            if (parent instanceof EnhancedForStatement) {
                EnhancedForStatement efStmt = (EnhancedForStatement) parent;
                expression = efStmt.getExpression();
                if (expression != null) {
                    ITypeBinding expBinding = expression.resolveTypeBinding();
                    if (expBinding != null) {
                        if (expBinding.isArray()) {
                            expressionTypeBinding = expBinding.getElementType();
                        } else {
                            // $NON-NLS-1$
                            ITypeBinding iterable = Bindings.findTypeInHierarchy(expBinding, "java.lang.Iterable");
                            if (iterable != null) {
                                ITypeBinding[] typeArguments = iterable.getTypeArguments();
                                if (typeArguments.length == 1) {
                                    expressionTypeBinding = typeArguments[0];
                                    expressionTypeBinding = Bindings.normalizeForDeclarationUse(expressionTypeBinding, context.getASTRoot().getAST());
                                }
                            }
                        }
                    }
                }
            }
        }
    } else if (varDeclaration instanceof VariableDeclarationFragment) {
        ASTNode parent = varDeclaration.getParent();
        expression = ((VariableDeclarationFragment) varDeclaration).getInitializer();
        if (expression != null) {
            expressionTypeBinding = expression.resolveTypeBinding();
        }
        if (parent instanceof VariableDeclarationStatement) {
            type = ((VariableDeclarationStatement) parent).getType();
        } else if (parent instanceof VariableDeclarationExpression) {
            VariableDeclarationExpression varDecl = (VariableDeclarationExpression) parent;
            // cannot convert a VariableDeclarationExpression with multiple fragments to var.
            if (varDecl.fragments().size() > 1) {
                return false;
            }
            type = varDecl.getType();
        }
    }
    if (type == null || type.isVar()) {
        return false;
    }
    if (expression == null || expression instanceof ArrayInitializer || expression instanceof LambdaExpression || expression instanceof MethodReference) {
        return false;
    }
    if (expressionTypeBinding == null || !expressionTypeBinding.isEqualTo(typeBinding)) {
        return false;
    }
    TypeChangeCorrectionProposal proposal = new TypeChangeCorrectionProposal(context.getCompilationUnit(), varBinding, astRoot, typeBinding, IProposalRelevance.CHANGE_VARIABLE);
    proposal.setKind(CodeActionKind.Refactor);
    proposals.add(proposal);
    return true;
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) IJavaElement(org.eclipse.jdt.core.IJavaElement) TypeChangeCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.TypeChangeCorrectionProposal) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) SimpleName(org.eclipse.jdt.core.dom.SimpleName) IBinding(org.eclipse.jdt.core.dom.IBinding) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) IVariableBinding(org.eclipse.jdt.core.dom.IVariableBinding) IType(org.eclipse.jdt.core.IType) Type(org.eclipse.jdt.core.dom.Type) IJavaProject(org.eclipse.jdt.core.IJavaProject) Expression(org.eclipse.jdt.core.dom.Expression) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) 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) EnhancedForStatement(org.eclipse.jdt.core.dom.EnhancedForStatement) MethodReference(org.eclipse.jdt.core.dom.MethodReference) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) ArrayInitializer(org.eclipse.jdt.core.dom.ArrayInitializer)

Aggregations

MethodReference (org.eclipse.jdt.core.dom.MethodReference)11 ASTNode (org.eclipse.jdt.core.dom.ASTNode)9 IMethodBinding (org.eclipse.jdt.core.dom.IMethodBinding)6 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)6 SingleVariableDeclaration (org.eclipse.jdt.core.dom.SingleVariableDeclaration)6 Type (org.eclipse.jdt.core.dom.Type)6 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)5 ArrayList (java.util.ArrayList)4 List (java.util.List)4 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)4 AST (org.eclipse.jdt.core.dom.AST)4 Block (org.eclipse.jdt.core.dom.Block)4 CompilationUnit (org.eclipse.jdt.core.dom.CompilationUnit)4 Expression (org.eclipse.jdt.core.dom.Expression)4 ExpressionStatement (org.eclipse.jdt.core.dom.ExpressionStatement)4 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)4 Statement (org.eclipse.jdt.core.dom.Statement)4 UnionType (org.eclipse.jdt.core.dom.UnionType)4 VariableDeclarationExpression (org.eclipse.jdt.core.dom.VariableDeclarationExpression)4 ASTRewrite (org.eclipse.jdt.core.dom.rewrite.ASTRewrite)4