Search in sources :

Example 1 with ExpressionMethodReference

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

the class QuickAssistProcessor method getAddMethodDeclaration.

public static boolean getAddMethodDeclaration(IInvocationContext context, ASTNode covering, Collection<ChangeCorrectionProposal> resultingCollections) {
    CompilationUnit astRoot = context.getASTRoot();
    ExpressionMethodReference methodReferenceNode = covering instanceof ExpressionMethodReference ? (ExpressionMethodReference) covering : ASTNodes.getParent(covering, ExpressionMethodReference.class);
    if (methodReferenceNode == null) {
        return false;
    }
    boolean addStaticModifier = false;
    TypeDeclaration typeDeclaration = ASTNodes.getParent(methodReferenceNode, TypeDeclaration.class);
    if (isTypeReferenceToInstanceMethod(methodReferenceNode)) {
        String methodReferenceQualifiedName = ((Name) methodReferenceNode.getExpression()).getFullyQualifiedName();
        String typeDeclarationName = astRoot.getPackage().getName().getFullyQualifiedName() + '.' + typeDeclaration.getName().getFullyQualifiedName();
        if (!methodReferenceQualifiedName.equals(typeDeclarationName) && !methodReferenceQualifiedName.equals(typeDeclaration.getName().getFullyQualifiedName())) {
            // only propose for references in same class
            return false;
        }
        addStaticModifier = true;
    }
    AST ast = astRoot.getAST();
    ASTRewrite rewrite = ASTRewrite.create(ast);
    ListRewrite listRewrite = rewrite.getListRewrite(typeDeclaration, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
    String label = Messages.format(CorrectionMessages.AddUnimplementedMethodReferenceOperation_AddMissingMethod_group, new String[] { methodReferenceNode.getName().getIdentifier(), typeDeclaration.getName().getIdentifier() });
    ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, CodeActionKind.QuickFix, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES);
    // ImportRewrite importRewrite= proposal.createImportRewrite(context.getASTRoot());
    ImportRewrite importRewrite = StubUtility.createImportRewrite(astRoot, true);
    VariableDeclarationStatement variableDeclarationStatement = ASTNodes.getParent(methodReferenceNode, VariableDeclarationStatement.class);
    MethodInvocation methodInvocationNode = ASTNodes.getParent(methodReferenceNode, MethodInvocation.class);
    Assignment variableAssignment = ASTNodes.getParent(methodReferenceNode, Assignment.class);
    if ((variableAssignment != null || variableDeclarationStatement != null) && methodInvocationNode == null) {
        /*
			 * variable declaration
			 */
        Type type = null;
        ReturnType returnType = null;
        if (variableDeclarationStatement != null) {
            type = variableDeclarationStatement.getType();
            returnType = getReturnType(ast, importRewrite, type);
        } else {
            Expression leftHandSide = variableAssignment.getLeftHandSide();
            ITypeBinding assignmentTypeBinding = leftHandSide.resolveTypeBinding();
            if (assignmentTypeBinding == null) {
                return false;
            }
            type = importRewrite.addImport(assignmentTypeBinding, ast);
            returnType = new ReturnType();
            returnType.type = type;
            returnType.binding = assignmentTypeBinding;
        }
        if (returnType.binding == null) {
            return false;
        }
        MethodDeclaration newMethodDeclaration = ast.newMethodDeclaration();
        newMethodDeclaration.setName((SimpleName) rewrite.createCopyTarget(methodReferenceNode.getName()));
        newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PRIVATE_KEYWORD));
        if (addStaticModifier) {
            newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD));
        }
        IMethodBinding functionalInterfaceMethod = variableDeclarationStatement == null ? returnType.binding.getFunctionalInterfaceMethod() : variableDeclarationStatement.getType().resolveBinding().getFunctionalInterfaceMethod();
        if (functionalInterfaceMethod != null) {
            returnType.type = importRewrite.addImport(functionalInterfaceMethod.getReturnType(), ast);
            returnType.binding = functionalInterfaceMethod.getReturnType();
            ITypeBinding[] typeArguments = functionalInterfaceMethod.getParameterTypes();
            for (int i = 0; i < typeArguments.length; i++) {
                ITypeBinding iTypeBinding = typeArguments[i];
                SingleVariableDeclaration newSingleVariableDeclaration = ast.newSingleVariableDeclaration();
                newSingleVariableDeclaration.setName(ast.newSimpleName(iTypeBinding.getErasure().getName().toLowerCase() + (i + 1)));
                newSingleVariableDeclaration.setType(importRewrite.addImport(iTypeBinding.getErasure(), ast));
                newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
            }
        }
        newMethodDeclaration.setReturnType2(returnType.type);
        Block newBlock = getNewReturnBlock(ast, returnType.binding);
        newMethodDeclaration.setBody(newBlock);
        listRewrite.insertLast(newMethodDeclaration, null);
        // add proposal
        resultingCollections.add(proposal);
        return true;
    }
    /*
		 * method invocation
		 */
    IMethodBinding methodBinding = methodInvocationNode == null ? null : methodInvocationNode.resolveMethodBinding();
    if (methodBinding == null) {
        return false;
    }
    List<ASTNode> arguments = methodInvocationNode.arguments();
    int index = -1;
    for (int i = 0; i < arguments.size(); i++) {
        ASTNode node = arguments.get(i);
        if (node.equals(methodReferenceNode)) {
            index = i;
            break;
        }
    }
    ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
    ITypeBinding[] typeArguments = methodBinding.getTypeArguments();
    ITypeBinding[] parameterTypesFunctionalInterface = parameterTypes[index].getFunctionalInterfaceMethod().getParameterTypes();
    ITypeBinding returnTypeBindingFunctionalInterface = parameterTypes[index].getFunctionalInterfaceMethod().getReturnType();
    MethodDeclaration newMethodDeclaration = ast.newMethodDeclaration();
    newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PRIVATE_KEYWORD));
    if (addStaticModifier) {
        newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD));
    }
    Type newReturnType = null;
    if (returnTypeBindingFunctionalInterface.isPrimitive()) {
        newReturnType = ast.newPrimitiveType(PrimitiveType.toCode(returnTypeBindingFunctionalInterface.getName()));
    } else {
        newReturnType = importRewrite.addImport(returnTypeBindingFunctionalInterface, ast);
        ITypeBinding[] typeParameters = typeDeclaration.resolveBinding().getTypeParameters();
        bIf: if (returnTypeBindingFunctionalInterface.isTypeVariable() || returnTypeBindingFunctionalInterface.isParameterizedType()) {
            for (ITypeBinding typeParameter : typeParameters) {
                // check if parameter type is a Type parameter of the class
                if (Bindings.equals(typeParameter, returnTypeBindingFunctionalInterface)) {
                    break bIf;
                }
            }
            TypeParameter newTypeParameter = ast.newTypeParameter();
            newTypeParameter.setName(ast.newSimpleName(returnTypeBindingFunctionalInterface.getName()));
            addIfMissing(newMethodDeclaration, newTypeParameter);
        }
    }
    newMethodDeclaration.setName((SimpleName) rewrite.createCopyTarget(methodReferenceNode.getName()));
    newMethodDeclaration.setReturnType2(newReturnType);
    pLoop: for (int i = 0; i < parameterTypesFunctionalInterface.length; i++) {
        ITypeBinding parameterType2 = parameterTypesFunctionalInterface[i];
        SingleVariableDeclaration newSingleVariableDeclaration = ast.newSingleVariableDeclaration();
        if (parameterType2.isCapture()) {
            newSingleVariableDeclaration.setName(ast.newSimpleName(parameterType2.getErasure().getName().toLowerCase() + (i + 1)));
            newSingleVariableDeclaration.setType(importRewrite.addImport(parameterType2.getErasure(), ast));
        } else {
            newSingleVariableDeclaration.setName(ast.newSimpleName(parameterType2.getName().toLowerCase() + (i + 1)));
            newSingleVariableDeclaration.setType(importRewrite.addImport(parameterType2, ast));
        }
        newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
        ITypeBinding[] typeParameters = typeDeclaration.resolveBinding().getTypeParameters();
        if (parameterType2.isTypeVariable()) {
            // check if parameter type is a Type parameter of the class
            for (ITypeBinding typeParameter : typeParameters) {
                if (Bindings.equals(typeParameter, parameterType2)) {
                    continue pLoop;
                }
            }
            TypeParameter newTypeParameter = ast.newTypeParameter();
            newTypeParameter.setName(ast.newSimpleName(importRewrite.addImport(parameterType2)));
            ITypeBinding[] typeBounds = parameterType2.getTypeBounds();
            for (ITypeBinding typeBound : typeBounds) {
                newTypeParameter.typeBounds().add(importRewrite.addImport(typeBound, ast));
            }
            addIfMissing(newMethodDeclaration, newTypeParameter);
        }
    }
    for (int i = 0; i < typeArguments.length; i++) {
        ITypeBinding typeArgument = typeArguments[i];
        SingleVariableDeclaration newSingleVariableDeclaration = ast.newSingleVariableDeclaration();
        newSingleVariableDeclaration.setName(ast.newSimpleName(typeArgument.getName().toLowerCase() + (i + 1)));
        newSingleVariableDeclaration.setType(importRewrite.addImport(typeArgument, ast));
        newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
        if (typeArgument.isTypeVariable()) {
            TypeParameter newTypeParameter = ast.newTypeParameter();
            newTypeParameter.setName(ast.newSimpleName(importRewrite.addImport(typeArgument)));
            newMethodDeclaration.typeParameters().add(newTypeParameter);
        }
    }
    Block newBlock = getNewReturnBlock(ast, returnTypeBindingFunctionalInterface);
    newMethodDeclaration.setBody(newBlock);
    listRewrite.insertLast(newMethodDeclaration, null);
    // add proposal
    resultingCollections.add(proposal);
    return true;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) TypeParameter(org.eclipse.jdt.core.dom.TypeParameter) ImportRewrite(org.eclipse.jdt.core.dom.rewrite.ImportRewrite) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) SuperMethodInvocation(org.eclipse.jdt.core.dom.SuperMethodInvocation) ListRewrite(org.eclipse.jdt.core.dom.rewrite.ListRewrite) SimpleName(org.eclipse.jdt.core.dom.SimpleName) Name(org.eclipse.jdt.core.dom.Name) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) Assignment(org.eclipse.jdt.core.dom.Assignment) ITypeBinding(org.eclipse.jdt.core.dom.ITypeBinding) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) VariableDeclarationStatement(org.eclipse.jdt.core.dom.VariableDeclarationStatement) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference) AST(org.eclipse.jdt.core.dom.AST) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) 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) Block(org.eclipse.jdt.core.dom.Block) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration)

Example 2 with ExpressionMethodReference

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

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

the class ObsoleteLambdaCleanUp method replaceByMethodReference.

private void replaceByMethodReference(final LambdaExpression node, final MethodInvocation methodInvocation) {
    ASTRewrite rewrite = cuRewrite.getASTRewrite();
    ASTNodeFactory ast = cuRewrite.getASTBuilder();
    TextEditGroup group = new TextEditGroup(MultiFixMessages.ObsoleteLambdaCleanUp_description);
    ExpressionMethodReference typeMethodRef = ast.newExpressionMethodReference();
    if (methodInvocation.getExpression() != null) {
        typeMethodRef.setExpression(ASTNodes.createMoveTarget(rewrite, methodInvocation.getExpression()));
    } else {
        typeMethodRef.setExpression(ast.newThisExpression());
    }
    typeMethodRef.setName(ASTNodes.createMoveTarget(rewrite, methodInvocation.getName()));
    ASTNodes.replaceButKeepComment(rewrite, node, typeMethodRef, group);
}
Also used : ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference) ASTNodeFactory(org.autorefactor.jdt.internal.corext.dom.ASTNodeFactory) ASTRewrite(org.autorefactor.jdt.core.dom.ASTRewrite) TextEditGroup(org.eclipse.text.edits.TextEditGroup)

Example 5 with ExpressionMethodReference

use of org.eclipse.jdt.core.dom.ExpressionMethodReference in project sts4 by spring-projects.

the class WebfluxRouterSymbolProvider method extractHandlerInformation.

private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, WebfluxRouteElement[] httpMethods, WebfluxRouteElement[] contentTypes, WebfluxRouteElement[] acceptTypes) {
    List<?> arguments = node.arguments();
    if (arguments != null) {
        for (Object argument : arguments) {
            if (argument instanceof ExpressionMethodReference) {
                ExpressionMethodReference methodReference = (ExpressionMethodReference) argument;
                IMethodBinding methodBinding = methodReference.resolveMethodBinding();
                if (methodBinding != null && methodBinding.getDeclaringClass() != null && methodBinding.getMethodDeclaration() != null) {
                    String handlerClass = methodBinding.getDeclaringClass().getBinaryName();
                    if (handlerClass != null)
                        handlerClass = handlerClass.trim();
                    String handlerMethod = methodBinding.getMethodDeclaration().toString();
                    if (handlerMethod != null)
                        handlerMethod = handlerMethod.trim();
                    return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, getElementStrings(httpMethods), getElementStrings(contentTypes), getElementStrings(acceptTypes));
                }
            }
        }
    }
    return null;
}
Also used : IMethodBinding(org.eclipse.jdt.core.dom.IMethodBinding) ExpressionMethodReference(org.eclipse.jdt.core.dom.ExpressionMethodReference)

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