Search in sources :

Example 1 with UnknownType

use of com.github.javaparser.ast.type.UnknownType in project javaparser by javaparser.

the class GeneratedJavaParserBase method generateLambda.

/**
 * Workaround for rather complex ambiguity that lambda's create
 */
Expression generateLambda(Expression ret, Statement lambdaBody) {
    if (ret instanceof EnclosedExpr) {
        Expression inner = ((EnclosedExpr) ret).getInner();
        SimpleName id = ((NameExpr) inner).getName();
        NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), EnumSet.noneOf(Modifier.class), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
        ret = new LambdaExpr(range(ret, lambdaBody), params, lambdaBody, true);
    } else if (ret instanceof NameExpr) {
        SimpleName id = ((NameExpr) ret).getName();
        NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), EnumSet.noneOf(Modifier.class), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
        ret = new LambdaExpr(range(ret, lambdaBody), params, lambdaBody, false);
    } else if (ret instanceof LambdaExpr) {
        ((LambdaExpr) ret).setBody(lambdaBody);
        propagateRangeGrowthOnRight(ret, lambdaBody);
    } else if (ret instanceof CastExpr) {
        CastExpr castExpr = (CastExpr) ret;
        Expression inner = generateLambda(castExpr.getExpression(), lambdaBody);
        castExpr.setExpression(inner);
    } else {
        addProblem("Failed to parse lambda expression! Please create an issue at https://github.com/javaparser/javaparser/issues");
    }
    return ret;
}
Also used : UnknownType(com.github.javaparser.ast.type.UnknownType) NodeList(com.github.javaparser.ast.NodeList) Parameter(com.github.javaparser.ast.body.Parameter) Modifier(com.github.javaparser.ast.Modifier)

Example 2 with UnknownType

use of com.github.javaparser.ast.type.UnknownType in project javaparser by javaparser.

the class ExpressionCompatibleWithType method reduce.

@Override
public ReductionResult reduce(BoundSet currentBoundSet) {
    if (isProperType(T)) {
        if (isCompatibleInALooseInvocationContext(typeSolver, expression, T)) {
            return ReductionResult.trueResult();
        } else {
            return ReductionResult.falseResult();
        }
    }
    if (isStandaloneExpression(expression)) {
        ResolvedType s = JavaParserFacade.get(typeSolver).getType(expression, false);
        return ReductionResult.empty().withConstraint(new TypeCompatibleWithType(typeSolver, s, T));
    }
    if (isPolyExpression(expression)) {
        if (expression instanceof EnclosedExpr) {
            EnclosedExpr enclosedExpr = (EnclosedExpr) expression;
            return ReductionResult.oneConstraint(new ExpressionCompatibleWithType(typeSolver, enclosedExpr.getInner(), T));
        }
        if (expression instanceof ObjectCreationExpr) {
            BoundSet B3 = new TypeInference(typeSolver).invocationTypeInferenceBoundsSetB3();
            return ReductionResult.bounds(B3);
        }
        if (expression instanceof MethodCallExpr) {
            throw new UnsupportedOperationException();
        }
        if (expression instanceof ConditionalExpr) {
            ConditionalExpr conditionalExpr = (ConditionalExpr) expression;
            return ReductionResult.withConstraints(new ExpressionCompatibleWithType(typeSolver, conditionalExpr.getThenExpr(), T), new ExpressionCompatibleWithType(typeSolver, conditionalExpr.getElseExpr(), T));
        }
        if (expression instanceof LambdaExpr) {
            LambdaExpr lambdaExpr = (LambdaExpr) expression;
            if (!FunctionalInterfaceLogic.isFunctionalInterfaceType(T)) {
                return ReductionResult.falseResult();
            }
            // - Otherwise, let T' be the ground target type derived from T, as specified in §15.27.3. If §18.5.3
            // is used to derive a functional interface type which is parameterized, then the test that
            // F<A'1, ..., A'm> is a subtype of F<A1, ..., Am> is not performed (instead, it is asserted with a
            // constraint formula below). Let the target function type for the lambda expression be the
            // function type of T'. Then:
            Pair<ResolvedType, Boolean> result = TypeHelper.groundTargetTypeOfLambda(lambdaExpr, T, typeSolver);
            ResolvedType TFirst = result.a;
            MethodType targetFunctionType = TypeHelper.getFunctionType(TFirst);
            targetFunctionType = replaceTypeVariablesWithInferenceVariables(targetFunctionType);
            if (result.b) {
                throw new UnsupportedOperationException();
            }
            if (targetFunctionType.getFormalArgumentTypes().size() != lambdaExpr.getParameters().size()) {
                return ReductionResult.falseResult();
            }
            if (targetFunctionType.getReturnType().isVoid()) {
                throw new UnsupportedOperationException();
            }
            if (!targetFunctionType.getReturnType().isVoid() && lambdaExpr.getBody() instanceof BlockStmt && !isValueCompatibleBlock(lambdaExpr.getBody())) {
                return ReductionResult.falseResult();
            }
            // - Otherwise, the constraint reduces to all of the following constraint formulas:
            List<ConstraintFormula> constraints = new LinkedList<>();
            // - If the lambda parameters have explicitly declared types F1, ..., Fn and the function type
            // has parameter types G1, ..., Gn, then i) for all i (1 ≤ i ≤ n), ‹Fi = Gi›, and ii) ‹T' <: T›.
            boolean hasExplicitlyDeclaredTypes = lambdaExpr.getParameters().stream().anyMatch(p -> !(p.getType() instanceof UnknownType));
            if (hasExplicitlyDeclaredTypes) {
                throw new UnsupportedOperationException();
            }
            if (!targetFunctionType.getReturnType().isVoid()) {
                ResolvedType R = targetFunctionType.getReturnType();
                if (TypeHelper.isProperType(R)) {
                    if (lambdaExpr.getBody() instanceof BlockStmt) {
                        List<Expression> resultExpressions = ExpressionHelper.getResultExpressions((BlockStmt) lambdaExpr.getBody());
                        for (Expression e : resultExpressions) {
                            if (!ExpressionHelper.isCompatibleInAssignmentContext(e, R, typeSolver)) {
                                return ReductionResult.falseResult();
                            }
                        }
                    } else {
                        Expression e = ((ExpressionStmt) lambdaExpr.getBody()).getExpression();
                        if (!ExpressionHelper.isCompatibleInAssignmentContext(e, R, typeSolver)) {
                            return ReductionResult.falseResult();
                        }
                    }
                } else {
                    if (lambdaExpr.getBody() instanceof BlockStmt) {
                        getAllReturnExpressions((BlockStmt) lambdaExpr.getBody()).forEach(e -> constraints.add(new ExpressionCompatibleWithType(typeSolver, e, R)));
                    } else {
                        // FEDERICO: Added - Start
                        for (int i = 0; i < lambdaExpr.getParameters().size(); i++) {
                            ResolvedType paramType = targetFunctionType.getFormalArgumentTypes().get(i);
                            TypeInferenceCache.record(typeSolver, lambdaExpr, lambdaExpr.getParameter(i).getNameAsString(), paramType);
                        }
                        // FEDERICO: Added - End
                        Expression e = ((ExpressionStmt) lambdaExpr.getBody()).getExpression();
                        constraints.add(new ExpressionCompatibleWithType(typeSolver, e, R));
                    }
                }
            }
            return ReductionResult.withConstraints(constraints);
        }
        if (expression instanceof MethodReferenceExpr) {
            throw new UnsupportedOperationException();
        }
        throw new RuntimeException("This should not happen");
    }
    throw new RuntimeException("This should not happen");
}
Also used : ResolvedType(com.github.javaparser.resolution.types.ResolvedType) LinkedList(java.util.LinkedList) UnknownType(com.github.javaparser.ast.type.UnknownType) ExpressionHelper.isStandaloneExpression(com.github.javaparser.symbolsolver.resolution.typeinference.ExpressionHelper.isStandaloneExpression) ExpressionHelper.isPolyExpression(com.github.javaparser.symbolsolver.resolution.typeinference.ExpressionHelper.isPolyExpression)

Aggregations

UnknownType (com.github.javaparser.ast.type.UnknownType)2 Modifier (com.github.javaparser.ast.Modifier)1 NodeList (com.github.javaparser.ast.NodeList)1 Parameter (com.github.javaparser.ast.body.Parameter)1 ResolvedType (com.github.javaparser.resolution.types.ResolvedType)1 ExpressionHelper.isPolyExpression (com.github.javaparser.symbolsolver.resolution.typeinference.ExpressionHelper.isPolyExpression)1 ExpressionHelper.isStandaloneExpression (com.github.javaparser.symbolsolver.resolution.typeinference.ExpressionHelper.isStandaloneExpression)1 LinkedList (java.util.LinkedList)1