Search in sources :

Example 6 with ASTRewriteCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal 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 7 with ASTRewriteCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class QuickAssistProcessor method getConvertLambdaToMethodReferenceProposal.

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

Example 8 with ASTRewriteCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class ModifierCorrectionSubProcessor method addAbstractMethodProposals.

public static void addAbstractMethodProposals(IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals) {
    ICompilationUnit cu = context.getCompilationUnit();
    CompilationUnit astRoot = context.getASTRoot();
    ASTNode selectedNode = problem.getCoveringNode(astRoot);
    if (selectedNode == null) {
        return;
    }
    MethodDeclaration decl;
    if (selectedNode instanceof SimpleName) {
        decl = (MethodDeclaration) selectedNode.getParent();
    } else if (selectedNode instanceof MethodDeclaration) {
        decl = (MethodDeclaration) selectedNode;
    } else {
        return;
    }
    ASTNode parentType = ASTResolving.findParentType(decl);
    TypeDeclaration parentTypeDecl = null;
    boolean parentIsAbstractClass = false;
    boolean parentIsInterface = false;
    if (parentType instanceof TypeDeclaration) {
        parentTypeDecl = (TypeDeclaration) parentType;
        parentIsAbstractClass = !parentTypeDecl.isInterface() && Modifier.isAbstract(parentTypeDecl.getModifiers());
        parentIsInterface = parentTypeDecl.isInterface();
    }
    boolean hasNoBody = decl.getBody() == null;
    int id = problem.getProblemId();
    if (id == IProblem.AbstractMethodInAbstractClass || id == IProblem.EnumAbstractMethodMustBeImplemented || id == IProblem.AbstractMethodInEnum || parentIsAbstractClass) {
        AST ast = astRoot.getAST();
        ASTRewrite rewrite = ASTRewrite.create(ast);
        removeModifier(decl, rewrite, Modifier.ABSTRACT);
        if (hasNoBody) {
            Block newBody = ast.newBlock();
            rewrite.set(decl, MethodDeclaration.BODY_PROPERTY, newBody, null);
            Type returnType = decl.getReturnType2();
            if (returnType != null) {
                Expression expr = ASTNodeFactory.newDefaultExpression(ast, returnType, decl.getExtraDimensions());
                if (expr != null) {
                    ReturnStatement returnStatement = ast.newReturnStatement();
                    returnStatement.setExpression(expr);
                    newBody.statements().add(returnStatement);
                }
            }
        }
        String label = CorrectionMessages.ModifierCorrectionSubProcessor_removeabstract_description;
        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, CodeActionKind.QuickFix, cu, rewrite, IProposalRelevance.REMOVE_ABSTRACT_MODIFIER);
        proposals.add(proposal);
    }
    if (!hasNoBody && id == IProblem.BodyForAbstractMethod) {
        AST ast = decl.getAST();
        {
            ASTRewrite rewrite = ASTRewrite.create(ast);
            rewrite.remove(decl.getBody(), null);
            int excluded;
            if (parentIsInterface) {
                excluded = ~(Modifier.PUBLIC | Modifier.ABSTRACT);
            } else {
                excluded = ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.ABSTRACT);
            }
            ModifierRewrite.create(rewrite, decl).setModifiers(0, excluded, null);
            String label = CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
            ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, CodeActionKind.QuickFix, cu, rewrite, IProposalRelevance.REMOVE_METHOD_BODY);
            proposals.add(proposal);
        }
        if (JavaModelUtil.is1d8OrHigher(cu.getJavaProject()) && parentIsInterface) {
            {
                // insert proposal to add static modifier
                String label = Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertostatic_description, decl.getName());
                int included = Modifier.STATIC;
                int excluded = Modifier.ABSTRACT | Modifier.DEFAULT;
                proposals.add(new ModifierChangeCorrectionProposal(label, cu, decl.resolveBinding(), decl, included, excluded, IProposalRelevance.ADD_STATIC_MODIFIER));
            }
            {
                // insert proposal to add default modifier
                String label = Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertodefault_description, decl.getName());
                int included = Modifier.DEFAULT;
                int excluded = Modifier.ABSTRACT | Modifier.STATIC;
                proposals.add(new ModifierChangeCorrectionProposal(label, cu, decl.resolveBinding(), decl, included, excluded, IProposalRelevance.ADD_DEFAULT_MODIFIER));
            }
        }
    }
    if (id == IProblem.AbstractMethodInAbstractClass && parentTypeDecl != null) {
        addMakeTypeAbstractProposal(context, parentTypeDecl, proposals);
    }
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) AST(org.eclipse.jdt.core.dom.AST) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) SimpleName(org.eclipse.jdt.core.dom.SimpleName) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) NameQualifiedType(org.eclipse.jdt.core.dom.NameQualifiedType) SimpleType(org.eclipse.jdt.core.dom.SimpleType) Type(org.eclipse.jdt.core.dom.Type) Expression(org.eclipse.jdt.core.dom.Expression) ModifierChangeCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ModifierChangeCorrectionProposal) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ReturnStatement(org.eclipse.jdt.core.dom.ReturnStatement) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) Block(org.eclipse.jdt.core.dom.Block) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration)

Example 9 with ASTRewriteCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class AdvancedQuickAssistProcessor method getSplitOrConditionProposals.

// 
// private static boolean getJoinOrIfStatementsProposals(IInvocationContext context, ASTNode covering, ArrayList<ASTNode> coveredNodes, Collection<ICommandAccess> resultingCollections) {
// Operator orOperator = InfixExpression.Operator.CONDITIONAL_OR;
// if (coveredNodes.size() < 2) {
// return false;
// }
// // check that all covered nodes are IfStatement's with same 'then' statement and without 'else'
// String commonThenSource = null;
// for (Iterator<ASTNode> iter = coveredNodes.iterator(); iter.hasNext();) {
// ASTNode node = iter.next();
// if (!(node instanceof IfStatement)) {
// return false;
// }
// //
// IfStatement ifStatement = (IfStatement) node;
// if (ifStatement.getElseStatement() != null) {
// return false;
// }
// //
// Statement thenStatement = ifStatement.getThenStatement();
// try {
// String thenSource = context.getCompilationUnit().getBuffer().getText(thenStatement.getStartPosition(), thenStatement.getLength());
// if (commonThenSource == null) {
// commonThenSource = thenSource;
// } else {
// if (!commonThenSource.equals(thenSource)) {
// return false;
// }
// }
// } catch (Throwable e) {
// return false;
// }
// }
// if (resultingCollections == null) {
// return true;
// }
// //
// final AST ast = covering.getAST();
// final ASTRewrite rewrite = ASTRewrite.create(ast);
// // prepare OR'ed condition
// InfixExpression condition = null;
// boolean hasRightOperand = false;
// Statement thenStatement = null;
// for (Iterator<ASTNode> iter = coveredNodes.iterator(); iter.hasNext();) {
// IfStatement ifStatement = (IfStatement) iter.next();
// if (thenStatement == null) {
// thenStatement = (Statement) rewrite.createCopyTarget(ifStatement.getThenStatement());
// }
// if (condition == null) {
// condition = ast.newInfixExpression();
// condition.setOperator(orOperator);
// condition.setLeftOperand(getParenthesizedExpressionIfNeeded(ast, rewrite, ifStatement.getExpression(), condition, InfixExpression.LEFT_OPERAND_PROPERTY));
// } else if (!hasRightOperand) {
// condition.setRightOperand(getParenthesizedExpressionIfNeeded(ast, rewrite, ifStatement.getExpression(), condition, InfixExpression.RIGHT_OPERAND_PROPERTY));
// hasRightOperand = true;
// } else {
// InfixExpression newCondition = ast.newInfixExpression();
// newCondition.setOperator(orOperator);
// newCondition.setLeftOperand(condition);
// newCondition.setRightOperand(getParenthesizedExpressionIfNeeded(ast, rewrite, ifStatement.getExpression(), condition, InfixExpression.RIGHT_OPERAND_PROPERTY));
// condition = newCondition;
// }
// }
// // prepare new IfStatement with OR'ed condition
// IfStatement newIf = ast.newIfStatement();
// newIf.setExpression(condition);
// newIf.setThenStatement(thenStatement);
// //
// ListRewrite listRewriter = null;
// for (Iterator<ASTNode> iter = coveredNodes.iterator(); iter.hasNext();) {
// IfStatement ifStatement = (IfStatement) iter.next();
// if (listRewriter == null) {
// Block sourceBlock = (Block) ifStatement.getParent();
// //int insertIndex = sourceBlock.statements().indexOf(ifStatement);
// listRewriter = rewrite.getListRewrite(sourceBlock, (ChildListPropertyDescriptor) ifStatement.getLocationInParent());
// }
// if (newIf != null) {
// listRewriter.replace(ifStatement, newIf, null);
// newIf = null;
// } else {
// listRewriter.remove(ifStatement, null);
// }
// }
// // add correction proposal
// String label = CorrectionMessages.AdvancedQuickAssistProcessor_joinWithOr_description;
// Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
// ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.JOIN_IF_STATEMENTS_WITH_OR, image);
// resultingCollections.add(proposal);
// return true;
// }
// 
public static boolean getSplitOrConditionProposals(IInvocationContext context, ASTNode node, Collection<CUCorrectionProposal> resultingCollections) {
    Operator orOperator = InfixExpression.Operator.CONDITIONAL_OR;
    // check that user invokes quick assist on infix expression
    if (!(node instanceof InfixExpression)) {
        return false;
    }
    InfixExpression infixExpression = (InfixExpression) node;
    if (infixExpression.getOperator() != orOperator) {
        return false;
    }
    int offset = isOperatorSelected(infixExpression, context.getSelectionOffset(), context.getSelectionLength());
    if (offset == -1) {
        return false;
    }
    // check that infix expression belongs to IfStatement
    Statement statement = ASTResolving.findParentStatement(node);
    if (!(statement instanceof IfStatement)) {
        return false;
    }
    IfStatement ifStatement = (IfStatement) statement;
    // check that infix expression is part of first level || condition of IfStatement
    InfixExpression topInfixExpression = infixExpression;
    while (topInfixExpression.getParent() instanceof InfixExpression && ((InfixExpression) topInfixExpression.getParent()).getOperator() == orOperator) {
        topInfixExpression = (InfixExpression) topInfixExpression.getParent();
    }
    if (ifStatement.getExpression() != topInfixExpression) {
        return false;
    }
    // 
    if (resultingCollections == null) {
        return true;
    }
    AST ast = ifStatement.getAST();
    ASTRewrite rewrite = ASTRewrite.create(ast);
    // prepare left and right conditions
    Expression[] newOperands = { null, null };
    breakInfixOperationAtOperation(rewrite, topInfixExpression, orOperator, offset, true, newOperands);
    Expression leftCondition = newOperands[0];
    Expression rightCondition = newOperands[1];
    // prepare first statement
    rewrite.replace(ifStatement.getExpression(), leftCondition, null);
    IfStatement secondIf = ast.newIfStatement();
    secondIf.setExpression(rightCondition);
    secondIf.setThenStatement((Statement) rewrite.createCopyTarget(ifStatement.getThenStatement()));
    Statement elseStatement = ifStatement.getElseStatement();
    if (elseStatement == null) {
        rewrite.set(ifStatement, IfStatement.ELSE_STATEMENT_PROPERTY, secondIf, null);
    } else {
        rewrite.replace(elseStatement, secondIf, null);
        secondIf.setElseStatement((Statement) rewrite.createMoveTarget(elseStatement));
    }
    // add correction proposal
    String label = CorrectionMessages.AdvancedQuickAssistProcessor_splitOrCondition_description;
    ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.SPLIT_OR_CONDITION);
    resultingCollections.add(proposal);
    return true;
}
Also used : Operator(org.eclipse.jdt.core.dom.InfixExpression.Operator) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) IfStatement(org.eclipse.jdt.core.dom.IfStatement) AST(org.eclipse.jdt.core.dom.AST) InfixExpression(org.eclipse.jdt.core.dom.InfixExpression) Expression(org.eclipse.jdt.core.dom.Expression) ParenthesizedExpression(org.eclipse.jdt.core.dom.ParenthesizedExpression) Statement(org.eclipse.jdt.core.dom.Statement) IfStatement(org.eclipse.jdt.core.dom.IfStatement) InfixExpression(org.eclipse.jdt.core.dom.InfixExpression) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite)

Example 10 with ASTRewriteCorrectionProposal

use of org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal in project eclipse.jdt.ls by eclipse.

the class ReturnTypeSubProcessor method addMissingReturnStatementProposals.

public static void addMissingReturnStatementProposals(IInvocationContext context, IProblemLocation problem, Collection<CUCorrectionProposal> proposals) {
    ICompilationUnit cu = context.getCompilationUnit();
    ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
    if (selectedNode == null) {
        return;
    }
    ReturnStatement existingStatement = (selectedNode instanceof ReturnStatement) ? (ReturnStatement) selectedNode : null;
    // Lambda Expression can be in a MethodDeclaration or a Field Declaration
    if (selectedNode instanceof LambdaExpression) {
        MissingReturnTypeInLambdaCorrectionProposal proposal = new MissingReturnTypeInLambdaCorrectionProposal(cu, (LambdaExpression) selectedNode, existingStatement, IProposalRelevance.MISSING_RETURN_TYPE);
        proposals.add(proposal);
    } else {
        BodyDeclaration decl = ASTResolving.findParentBodyDeclaration(selectedNode);
        if (decl instanceof MethodDeclaration) {
            MethodDeclaration methodDecl = (MethodDeclaration) decl;
            Block block = methodDecl.getBody();
            if (block == null) {
                return;
            }
            proposals.add(new MissingReturnTypeCorrectionProposal(cu, methodDecl, existingStatement, IProposalRelevance.MISSING_RETURN_TYPE));
            Type returnType = methodDecl.getReturnType2();
            if (returnType != null && !"void".equals(ASTNodes.asString(returnType))) {
                // $NON-NLS-1$
                AST ast = methodDecl.getAST();
                ASTRewrite rewrite = ASTRewrite.create(ast);
                rewrite.replace(returnType, ast.newPrimitiveType(PrimitiveType.VOID), null);
                Javadoc javadoc = methodDecl.getJavadoc();
                if (javadoc != null) {
                    TagElement tagElement = JavadocTagsSubProcessor.findTag(javadoc, TagElement.TAG_RETURN, null);
                    if (tagElement != null) {
                        rewrite.remove(tagElement, null);
                    }
                }
                String label = CorrectionMessages.ReturnTypeSubProcessor_changetovoid_description;
                ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, cu, rewrite, IProposalRelevance.CHANGE_RETURN_TYPE_TO_VOID);
                proposals.add(proposal);
            }
        }
    }
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) AST(org.eclipse.jdt.core.dom.AST) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) MissingReturnTypeInLambdaCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.MissingReturnTypeInLambdaCorrectionProposal) Javadoc(org.eclipse.jdt.core.dom.Javadoc) ASTRewriteCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal) Type(org.eclipse.jdt.core.dom.Type) PrimitiveType(org.eclipse.jdt.core.dom.PrimitiveType) MissingReturnTypeCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.MissingReturnTypeCorrectionProposal) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ReturnStatement(org.eclipse.jdt.core.dom.ReturnStatement) Block(org.eclipse.jdt.core.dom.Block) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) TagElement(org.eclipse.jdt.core.dom.TagElement) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration) LambdaExpression(org.eclipse.jdt.core.dom.LambdaExpression)

Aggregations

ASTRewrite (org.eclipse.jdt.core.dom.rewrite.ASTRewrite)15 ASTRewriteCorrectionProposal (org.eclipse.jdt.ls.core.internal.corrections.proposals.ASTRewriteCorrectionProposal)15 AST (org.eclipse.jdt.core.dom.AST)14 ASTNode (org.eclipse.jdt.core.dom.ASTNode)11 Expression (org.eclipse.jdt.core.dom.Expression)10 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)9 ReturnStatement (org.eclipse.jdt.core.dom.ReturnStatement)9 Type (org.eclipse.jdt.core.dom.Type)9 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)7 Block (org.eclipse.jdt.core.dom.Block)7 PrimitiveType (org.eclipse.jdt.core.dom.PrimitiveType)7 BodyDeclaration (org.eclipse.jdt.core.dom.BodyDeclaration)6 LambdaExpression (org.eclipse.jdt.core.dom.LambdaExpression)6 Statement (org.eclipse.jdt.core.dom.Statement)6 InfixExpression (org.eclipse.jdt.core.dom.InfixExpression)5 NameQualifiedType (org.eclipse.jdt.core.dom.NameQualifiedType)5 ParenthesizedExpression (org.eclipse.jdt.core.dom.ParenthesizedExpression)5 PrefixExpression (org.eclipse.jdt.core.dom.PrefixExpression)5 SimpleName (org.eclipse.jdt.core.dom.SimpleName)5 SimpleType (org.eclipse.jdt.core.dom.SimpleType)5