Search in sources :

Example 6 with ExpressionMethodReference

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

ExpressionMethodReference (org.eclipse.jdt.core.dom.ExpressionMethodReference)6 IMethodBinding (org.eclipse.jdt.core.dom.IMethodBinding)5 AST (org.eclipse.jdt.core.dom.AST)4 ArrayType (org.eclipse.jdt.core.dom.ArrayType)4 Block (org.eclipse.jdt.core.dom.Block)4 Expression (org.eclipse.jdt.core.dom.Expression)4 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)4 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)4 MethodInvocation (org.eclipse.jdt.core.dom.MethodInvocation)4 Name (org.eclipse.jdt.core.dom.Name)4 NameQualifiedType (org.eclipse.jdt.core.dom.NameQualifiedType)4 ParameterizedType (org.eclipse.jdt.core.dom.ParameterizedType)4 SimpleName (org.eclipse.jdt.core.dom.SimpleName)4 SimpleType (org.eclipse.jdt.core.dom.SimpleType)4 SuperMethodInvocation (org.eclipse.jdt.core.dom.SuperMethodInvocation)4 ThisExpression (org.eclipse.jdt.core.dom.ThisExpression)4 Type (org.eclipse.jdt.core.dom.Type)4 UnionType (org.eclipse.jdt.core.dom.UnionType)4 ImportRewrite (org.eclipse.jdt.core.dom.rewrite.ImportRewrite)4 ArrayList (java.util.ArrayList)3