Search in sources :

Example 1 with SuperMethodReference

use of org.eclipse.jdt.core.dom.SuperMethodReference 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 2 with SuperMethodReference

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

the class ObsoleteLambdaCleanUp method replaceBySuperMethodReference.

private void replaceBySuperMethodReference(final LambdaExpression node, final SuperMethodInvocation ci) {
    ASTRewrite rewrite = cuRewrite.getASTRewrite();
    ASTNodeFactory ast = cuRewrite.getASTBuilder();
    TextEditGroup group = new TextEditGroup(MultiFixMessages.ObsoleteLambdaCleanUp_description);
    SuperMethodReference creationRef = ast.newSuperMethodReference();
    creationRef.setName(ASTNodes.createMoveTarget(rewrite, ci.getName()));
    ASTNodes.replaceButKeepComment(rewrite, node, creationRef, group);
}
Also used : ASTNodeFactory(org.autorefactor.jdt.internal.corext.dom.ASTNodeFactory) ASTRewrite(org.autorefactor.jdt.core.dom.ASTRewrite) SuperMethodReference(org.eclipse.jdt.core.dom.SuperMethodReference) TextEditGroup(org.eclipse.text.edits.TextEditGroup)

Example 3 with SuperMethodReference

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

the class QuickAssistProcessor method convertMethodRefernceToLambda.

/**
 * Converts and replaces the given method reference with corresponding lambda
 * expression in the given ASTRewrite.
 *
 * @param methodReference
 *            the method reference to convert
 * @param functionalMethod
 *            the non-generic functional interface method to be implemented by
 *            the lambda expression
 * @param astRoot
 *            the AST root
 * @param rewrite
 *            the ASTRewrite
 * @param linkedProposalModel
 *            to create linked proposals for lambda's parameters or
 *            <code>null</code> if linked proposals are not required
 * @param createBlockBody
 *            <code>true</code> if lambda expression's body should be a block
 *
 * @return lambda expression used to replace the method reference in the given
 *         ASTRewrite
 * @throws JavaModelException
 *             if an exception occurs while accessing the Java element
 *             corresponding to the <code>functionalMethod</code>
 */
public static LambdaExpression convertMethodRefernceToLambda(MethodReference methodReference, IMethodBinding functionalMethod, CompilationUnit astRoot, ASTRewrite rewrite, LinkedProposalModel linkedProposalModel, boolean createBlockBody) throws JavaModelException {
    AST ast = astRoot.getAST();
    LambdaExpression lambda = ast.newLambdaExpression();
    String[] lambdaParamNames = getUniqueParameterNames(methodReference, functionalMethod);
    List<VariableDeclaration> lambdaParameters = lambda.parameters();
    for (int i = 0; i < lambdaParamNames.length; i++) {
        String paramName = lambdaParamNames[i];
        VariableDeclarationFragment lambdaParameter = ast.newVariableDeclarationFragment();
        SimpleName name = ast.newSimpleName(paramName);
        lambdaParameter.setName(name);
        lambdaParameters.add(lambdaParameter);
        if (linkedProposalModel != null) {
            linkedProposalModel.getPositionGroup(name.getIdentifier(), true).addPosition(rewrite.track(name), i == 0);
        }
    }
    int noOfLambdaParameters = lambdaParamNames.length;
    lambda.setParentheses(noOfLambdaParameters != 1);
    ITypeBinding returnTypeBinding = functionalMethod.getReturnType();
    // too often null, see bug 440000, bug 440344, bug 333665
    IMethodBinding referredMethodBinding = methodReference.resolveMethodBinding();
    if (methodReference instanceof CreationReference) {
        CreationReference creationRef = (CreationReference) methodReference;
        Type type = creationRef.getType();
        if (type instanceof ArrayType) {
            ArrayCreation arrayCreation = ast.newArrayCreation();
            if (createBlockBody) {
                Block blockBody = getBlockBodyForLambda(arrayCreation, returnTypeBinding, ast);
                lambda.setBody(blockBody);
            } else {
                lambda.setBody(arrayCreation);
            }
            ArrayType arrayType = (ArrayType) type;
            Type copiedElementType = (Type) rewrite.createCopyTarget(arrayType.getElementType());
            arrayCreation.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions()));
            SimpleName name = ast.newSimpleName(lambdaParamNames[0]);
            arrayCreation.dimensions().add(name);
            if (linkedProposalModel != null) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        } else {
            ClassInstanceCreation cic = ast.newClassInstanceCreation();
            if (createBlockBody) {
                Block blockBody = getBlockBodyForLambda(cic, returnTypeBinding, ast);
                lambda.setBody(blockBody);
            } else {
                lambda.setBody(cic);
            }
            ITypeBinding typeBinding = type.resolveBinding();
            if (!(type instanceof ParameterizedType) && typeBinding != null && typeBinding.getTypeDeclaration().isGenericType()) {
                cic.setType(ast.newParameterizedType((Type) rewrite.createCopyTarget(type)));
            } else {
                cic.setType((Type) rewrite.createCopyTarget(type));
            }
            List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
            cic.arguments().addAll(invocationArgs);
            if (linkedProposalModel != null) {
                for (SimpleName name : invocationArgs) {
                    linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
                }
            }
            cic.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
        }
    } else if (referredMethodBinding != null && Modifier.isStatic(referredMethodBinding.getModifiers())) {
        MethodInvocation methodInvocation = ast.newMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(methodInvocation);
        }
        Expression expr = null;
        boolean hasConflict = hasConflict(methodReference.getStartPosition(), referredMethodBinding, ScopeAnalyzer.METHODS | ScopeAnalyzer.CHECK_VISIBILITY, astRoot);
        if (hasConflict || !Bindings.isSuperType(referredMethodBinding.getDeclaringClass(), ASTNodes.getEnclosingType(methodReference)) || methodReference.typeArguments().size() != 0) {
            if (methodReference instanceof ExpressionMethodReference) {
                ExpressionMethodReference expressionMethodReference = (ExpressionMethodReference) methodReference;
                expr = (Expression) rewrite.createCopyTarget(expressionMethodReference.getExpression());
            } else if (methodReference instanceof TypeMethodReference) {
                Type type = ((TypeMethodReference) methodReference).getType();
                ITypeBinding typeBinding = type.resolveBinding();
                if (typeBinding != null) {
                    ImportRewrite importRewrite = CodeStyleConfiguration.createImportRewrite(astRoot, true);
                    expr = ast.newName(importRewrite.addImport(typeBinding));
                }
            }
        }
        methodInvocation.setExpression(expr);
        SimpleName methodName = getMethodInvocationName(methodReference);
        methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
        methodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    } else if (methodReference instanceof SuperMethodReference) {
        SuperMethodInvocation superMethodInvocation = ast.newSuperMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(superMethodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(superMethodInvocation);
        }
        Name superQualifier = ((SuperMethodReference) methodReference).getQualifier();
        if (superQualifier != null) {
            superMethodInvocation.setQualifier((Name) rewrite.createCopyTarget(superQualifier));
        }
        SimpleName methodName = getMethodInvocationName(methodReference);
        superMethodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
        superMethodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        superMethodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    } else {
        MethodInvocation methodInvocation = ast.newMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(methodInvocation);
        }
        boolean isTypeReference = isTypeReferenceToInstanceMethod(methodReference);
        if (isTypeReference) {
            SimpleName name = ast.newSimpleName(lambdaParamNames[0]);
            methodInvocation.setExpression(name);
            if (linkedProposalModel != null) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        } else {
            Expression expr = ((ExpressionMethodReference) methodReference).getExpression();
            if (!(expr instanceof ThisExpression && methodReference.typeArguments().size() == 0)) {
                methodInvocation.setExpression((Expression) rewrite.createCopyTarget(expr));
            }
        }
        SimpleName methodName = getMethodInvocationName(methodReference);
        methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, isTypeReference ? 1 : 0, noOfLambdaParameters, lambdaParamNames);
        methodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    }
    rewrite.replace(methodReference, lambda, null);
    return lambda;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) SimpleName(org.eclipse.jdt.core.dom.SimpleName) 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) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) ThisExpression(org.eclipse.jdt.core.dom.ThisExpression) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) VariableDeclaration(org.eclipse.jdt.core.dom.VariableDeclaration) TypeMethodReference(org.eclipse.jdt.core.dom.TypeMethodReference) List(java.util.List) ArrayList(java.util.ArrayList) 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) NameQualifiedType(org.eclipse.jdt.core.dom.NameQualifiedType) IType(org.eclipse.jdt.core.IType) UnionType(org.eclipse.jdt.core.dom.UnionType) ArrayType(org.eclipse.jdt.core.dom.ArrayType) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) SimpleType(org.eclipse.jdt.core.dom.SimpleType) Type(org.eclipse.jdt.core.dom.Type) ThisExpression(org.eclipse.jdt.core.dom.ThisExpression) Expression(org.eclipse.jdt.core.dom.Expression) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression) ArrayCreation(org.eclipse.jdt.core.dom.ArrayCreation) Block(org.eclipse.jdt.core.dom.Block) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Example 4 with SuperMethodReference

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

the class QuickAssistProcessor method convertMethodRefernceToLambda.

/**
 * Converts and replaces the given method reference with corresponding lambda
 * expression in the given ASTRewrite.
 *
 * @param methodReference
 *            the method reference to convert
 * @param functionalMethod
 *            the non-generic functional interface method to be implemented by
 *            the lambda expression
 * @param astRoot
 *            the AST root
 * @param rewrite
 *            the ASTRewrite
 * @param linkedProposalModel
 *            to create linked proposals for lambda's parameters or
 *            <code>null</code> if linked proposals are not required
 * @param createBlockBody
 *            <code>true</code> if lambda expression's body should be a block
 *
 * @return lambda expression used to replace the method reference in the given
 *         ASTRewrite
 * @throws JavaModelException
 *             if an exception occurs while accessing the Java element
 *             corresponding to the <code>functionalMethod</code>
 */
public static LambdaExpression convertMethodRefernceToLambda(MethodReference methodReference, IMethodBinding functionalMethod, CompilationUnit astRoot, ASTRewrite rewrite, LinkedProposalModelCore linkedProposalModel, boolean createBlockBody) throws JavaModelException {
    AST ast = astRoot.getAST();
    LambdaExpression lambda = ast.newLambdaExpression();
    String[] lambdaParamNames = getUniqueParameterNames(methodReference, functionalMethod);
    List<VariableDeclaration> lambdaParameters = lambda.parameters();
    for (int i = 0; i < lambdaParamNames.length; i++) {
        String paramName = lambdaParamNames[i];
        VariableDeclarationFragment lambdaParameter = ast.newVariableDeclarationFragment();
        SimpleName name = ast.newSimpleName(paramName);
        lambdaParameter.setName(name);
        lambdaParameters.add(lambdaParameter);
        if (linkedProposalModel != null) {
            linkedProposalModel.getPositionGroup(name.getIdentifier(), true).addPosition(rewrite.track(name), i == 0);
        }
    }
    int noOfLambdaParameters = lambdaParamNames.length;
    lambda.setParentheses(noOfLambdaParameters != 1);
    ITypeBinding returnTypeBinding = functionalMethod.getReturnType();
    // too often null, see bug 440000, bug 440344, bug 333665
    IMethodBinding referredMethodBinding = methodReference.resolveMethodBinding();
    if (methodReference instanceof CreationReference) {
        CreationReference creationRef = (CreationReference) methodReference;
        Type type = creationRef.getType();
        if (type instanceof ArrayType) {
            ArrayCreation arrayCreation = ast.newArrayCreation();
            if (createBlockBody) {
                Block blockBody = getBlockBodyForLambda(arrayCreation, returnTypeBinding, ast);
                lambda.setBody(blockBody);
            } else {
                lambda.setBody(arrayCreation);
            }
            ArrayType arrayType = (ArrayType) type;
            Type copiedElementType = (Type) rewrite.createCopyTarget(arrayType.getElementType());
            arrayCreation.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions()));
            SimpleName name = ast.newSimpleName(lambdaParamNames[0]);
            arrayCreation.dimensions().add(name);
            if (linkedProposalModel != null) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        } else {
            ClassInstanceCreation cic = ast.newClassInstanceCreation();
            if (createBlockBody) {
                Block blockBody = getBlockBodyForLambda(cic, returnTypeBinding, ast);
                lambda.setBody(blockBody);
            } else {
                lambda.setBody(cic);
            }
            ITypeBinding typeBinding = type.resolveBinding();
            if (!(type instanceof ParameterizedType) && typeBinding != null && typeBinding.getTypeDeclaration().isGenericType()) {
                cic.setType(ast.newParameterizedType((Type) rewrite.createCopyTarget(type)));
            } else {
                cic.setType((Type) rewrite.createCopyTarget(type));
            }
            List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
            cic.arguments().addAll(invocationArgs);
            if (linkedProposalModel != null) {
                for (SimpleName name : invocationArgs) {
                    linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
                }
            }
            cic.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
        }
    } else if (referredMethodBinding != null && Modifier.isStatic(referredMethodBinding.getModifiers())) {
        MethodInvocation methodInvocation = ast.newMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(methodInvocation);
        }
        Expression expr = null;
        boolean hasConflict = hasConflict(methodReference.getStartPosition(), referredMethodBinding, ScopeAnalyzer.METHODS | ScopeAnalyzer.CHECK_VISIBILITY, astRoot);
        if (hasConflict || !Bindings.isSuperType(referredMethodBinding.getDeclaringClass(), ASTNodes.getEnclosingType(methodReference)) || methodReference.typeArguments().size() != 0) {
            if (methodReference instanceof ExpressionMethodReference) {
                ExpressionMethodReference expressionMethodReference = (ExpressionMethodReference) methodReference;
                expr = (Expression) rewrite.createCopyTarget(expressionMethodReference.getExpression());
            } else if (methodReference instanceof TypeMethodReference) {
                Type type = ((TypeMethodReference) methodReference).getType();
                ITypeBinding typeBinding = type.resolveBinding();
                if (typeBinding != null) {
                    ImportRewrite importRewrite = CodeStyleConfiguration.createImportRewrite(astRoot, true);
                    expr = ast.newName(importRewrite.addImport(typeBinding));
                }
            }
        }
        methodInvocation.setExpression(expr);
        SimpleName methodName = getMethodInvocationName(methodReference);
        methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
        methodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    } else if (methodReference instanceof SuperMethodReference) {
        SuperMethodInvocation superMethodInvocation = ast.newSuperMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(superMethodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(superMethodInvocation);
        }
        Name superQualifier = ((SuperMethodReference) methodReference).getQualifier();
        if (superQualifier != null) {
            superMethodInvocation.setQualifier((Name) rewrite.createCopyTarget(superQualifier));
        }
        SimpleName methodName = getMethodInvocationName(methodReference);
        superMethodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
        superMethodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        superMethodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    } else {
        MethodInvocation methodInvocation = ast.newMethodInvocation();
        if (createBlockBody) {
            Block blockBody = getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
            lambda.setBody(blockBody);
        } else {
            lambda.setBody(methodInvocation);
        }
        boolean isTypeReference = isTypeReferenceToInstanceMethod(methodReference);
        if (isTypeReference) {
            SimpleName name = ast.newSimpleName(lambdaParamNames[0]);
            methodInvocation.setExpression(name);
            if (linkedProposalModel != null) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        } else {
            Expression expr = ((ExpressionMethodReference) methodReference).getExpression();
            if (!(expr instanceof ThisExpression && methodReference.typeArguments().size() == 0)) {
                methodInvocation.setExpression((Expression) rewrite.createCopyTarget(expr));
            }
        }
        SimpleName methodName = getMethodInvocationName(methodReference);
        methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
        List<SimpleName> invocationArgs = getInvocationArguments(ast, isTypeReference ? 1 : 0, noOfLambdaParameters, lambdaParamNames);
        methodInvocation.arguments().addAll(invocationArgs);
        if (linkedProposalModel != null) {
            for (SimpleName name : invocationArgs) {
                linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
            }
        }
        methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
    }
    rewrite.replace(methodReference, lambda, null);
    return lambda;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) SimpleName(org.eclipse.jdt.core.dom.SimpleName) 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) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) ThisExpression(org.eclipse.jdt.core.dom.ThisExpression) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) VariableDeclaration(org.eclipse.jdt.core.dom.VariableDeclaration) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) TypeMethodReference(org.eclipse.jdt.core.dom.TypeMethodReference) ArrayList(java.util.ArrayList) List(java.util.List) 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) 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) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Aggregations

SuperMethodReference (org.eclipse.jdt.core.dom.SuperMethodReference)4 ArrayList (java.util.ArrayList)3 List (java.util.List)3 AST (org.eclipse.jdt.core.dom.AST)3 ArrayCreation (org.eclipse.jdt.core.dom.ArrayCreation)3 ArrayType (org.eclipse.jdt.core.dom.ArrayType)3 Block (org.eclipse.jdt.core.dom.Block)3 ClassInstanceCreation (org.eclipse.jdt.core.dom.ClassInstanceCreation)3 CreationReference (org.eclipse.jdt.core.dom.CreationReference)3 Expression (org.eclipse.jdt.core.dom.Expression)3 ExpressionMethodReference (org.eclipse.jdt.core.dom.ExpressionMethodReference)3 IMethodBinding (org.eclipse.jdt.core.dom.IMethodBinding)3 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)3 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)3 MethodInvocation (org.eclipse.jdt.core.dom.MethodInvocation)3 Name (org.eclipse.jdt.core.dom.Name)3 NameQualifiedType (org.eclipse.jdt.core.dom.NameQualifiedType)3 ParameterizedType (org.eclipse.jdt.core.dom.ParameterizedType)3 SimpleName (org.eclipse.jdt.core.dom.SimpleName)3 SimpleType (org.eclipse.jdt.core.dom.SimpleType)3