Search in sources :

Example 16 with LambdaExpr

use of com.github.javaparser.ast.expr.LambdaExpr in project javaparser by javaparser.

the class TypeExtractor method resolveLambda.

private ResolvedType resolveLambda(LambdaExpr node, ResolvedType result) {
    // We need to replace the type variables
    Context ctx = JavaParserFactory.getContext(node, typeSolver);
    result = solveGenericTypes(result, ctx);
    // We should find out which is the functional method (e.g., apply) and replace the params of the
    // solveLambdas with it, to derive so the values. We should also consider the value returned by the
    // lambdas
    Optional<MethodUsage> functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result);
    if (functionalMethod.isPresent()) {
        LambdaExpr lambdaExpr = node;
        InferenceContext lambdaCtx = new InferenceContext(MyObjectProvider.INSTANCE);
        InferenceContext funcInterfaceCtx = new InferenceContext(MyObjectProvider.INSTANCE);
        // At this point parameterType
        // if Function<T=? super Stream.T, ? extends map.R>
        // we should replace Stream.T
        ResolvedType functionalInterfaceType = ReferenceTypeImpl.undeterminedParameters(functionalMethod.get().getDeclaration().declaringType(), typeSolver);
        lambdaCtx.addPair(result, functionalInterfaceType);
        ResolvedType actualType;
        if (lambdaExpr.getBody() instanceof ExpressionStmt) {
            actualType = facade.getType(((ExpressionStmt) lambdaExpr.getBody()).getExpression());
        } else if (lambdaExpr.getBody() instanceof BlockStmt) {
            BlockStmt blockStmt = (BlockStmt) lambdaExpr.getBody();
            // Get all the return statements in the lambda block
            List<ReturnStmt> returnStmts = blockStmt.findAll(ReturnStmt.class);
            if (returnStmts.size() > 0) {
                actualType = returnStmts.stream().map(returnStmt -> returnStmt.getExpression().map(e -> facade.getType(e)).orElse(ResolvedVoidType.INSTANCE)).filter(x -> x != null && !x.isVoid() && !x.isNull()).findFirst().orElse(ResolvedVoidType.INSTANCE);
            } else {
                actualType = ResolvedVoidType.INSTANCE;
            }
        } else {
            throw new UnsupportedOperationException();
        }
        ResolvedType formalType = functionalMethod.get().returnType();
        // Infer the functional interfaces' return vs actual type
        funcInterfaceCtx.addPair(formalType, actualType);
        // Substitute to obtain a new type
        ResolvedType functionalTypeWithReturn = funcInterfaceCtx.resolve(funcInterfaceCtx.addSingle(functionalInterfaceType));
        // we don't need to bother inferring types
        if (!(formalType instanceof ResolvedVoidType)) {
            lambdaCtx.addPair(result, functionalTypeWithReturn);
            result = lambdaCtx.resolve(lambdaCtx.addSingle(result));
        }
    }
    return result;
}
Also used : Context(com.github.javaparser.symbolsolver.core.resolution.Context) InferenceContext(com.github.javaparser.symbolsolver.logic.InferenceContext) ArrayAccessExpr(com.github.javaparser.ast.expr.ArrayAccessExpr) ClassExpr(com.github.javaparser.ast.expr.ClassExpr) ClassOrInterfaceType(com.github.javaparser.ast.type.ClassOrInterfaceType) InstanceOfExpr(com.github.javaparser.ast.expr.InstanceOfExpr) ThisExpr(com.github.javaparser.ast.expr.ThisExpr) Pair(com.github.javaparser.utils.Pair) TypeHelper(com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper) NullLiteralExpr(com.github.javaparser.ast.expr.NullLiteralExpr) ResolvedReferenceTypeDeclaration(com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration) CharLiteralExpr(com.github.javaparser.ast.expr.CharLiteralExpr) Type(com.github.javaparser.ast.type.Type) Context(com.github.javaparser.symbolsolver.core.resolution.Context) ObjectCreationExpr(com.github.javaparser.ast.expr.ObjectCreationExpr) Expression(com.github.javaparser.ast.expr.Expression) CompilationUnit(com.github.javaparser.ast.CompilationUnit) BinaryExpr(com.github.javaparser.ast.expr.BinaryExpr) JavaParserFacade.solveGenericTypes(com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes) Node(com.github.javaparser.ast.Node) UnknownType(com.github.javaparser.ast.type.UnknownType) ArrayCreationExpr(com.github.javaparser.ast.expr.ArrayCreationExpr) ResolvedMethodDeclaration(com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration) MethodCallExpr(com.github.javaparser.ast.expr.MethodCallExpr) ResolvedTypeDeclaration(com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration) StringLiteralExpr(com.github.javaparser.ast.expr.StringLiteralExpr) EnclosedExpr(com.github.javaparser.ast.expr.EnclosedExpr) VariableDeclarationExpr(com.github.javaparser.ast.expr.VariableDeclarationExpr) FunctionalInterfaceLogic(com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic) List(java.util.List) UnaryExpr(com.github.javaparser.ast.expr.UnaryExpr) ResolvedPrimitiveType(com.github.javaparser.resolution.types.ResolvedPrimitiveType) Optional(java.util.Optional) LongLiteralExpr(com.github.javaparser.ast.expr.LongLiteralExpr) BlockStmt(com.github.javaparser.ast.stmt.BlockStmt) SymbolSolver(com.github.javaparser.symbolsolver.resolution.SymbolSolver) ArrayInitializerExpr(com.github.javaparser.ast.expr.ArrayInitializerExpr) FieldAccessExpr(com.github.javaparser.ast.expr.FieldAccessExpr) TypeExpr(com.github.javaparser.ast.expr.TypeExpr) NullType(com.github.javaparser.symbolsolver.model.typesystem.NullType) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) ExpressionStmt(com.github.javaparser.ast.stmt.ExpressionStmt) ConditionalExpr(com.github.javaparser.ast.expr.ConditionalExpr) ReturnStmt(com.github.javaparser.ast.stmt.ReturnStmt) Parameter(com.github.javaparser.ast.body.Parameter) MethodUsage(com.github.javaparser.resolution.MethodUsage) Value(com.github.javaparser.symbolsolver.model.resolution.Value) CastExpr(com.github.javaparser.ast.expr.CastExpr) VariableDeclarator(com.github.javaparser.ast.body.VariableDeclarator) ResolvedTypeParameterDeclaration(com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration) Log(com.github.javaparser.utils.Log) ResolvedType(com.github.javaparser.resolution.types.ResolvedType) ImmutableList(com.google.common.collect.ImmutableList) ResolvedArrayType(com.github.javaparser.resolution.types.ResolvedArrayType) DoubleLiteralExpr(com.github.javaparser.ast.expr.DoubleLiteralExpr) SuperExpr(com.github.javaparser.ast.expr.SuperExpr) Navigator.demandParentNode(com.github.javaparser.symbolsolver.javaparser.Navigator.demandParentNode) MyObjectProvider(com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider) JavaParserSymbolDeclaration(com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration) BooleanLiteralExpr(com.github.javaparser.ast.expr.BooleanLiteralExpr) UnsolvedSymbolException(com.github.javaparser.resolution.UnsolvedSymbolException) InferenceContext(com.github.javaparser.symbolsolver.logic.InferenceContext) TypeSolver(com.github.javaparser.symbolsolver.model.resolution.TypeSolver) ReferenceTypeImpl(com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl) AssignExpr(com.github.javaparser.ast.expr.AssignExpr) ReflectionClassDeclaration(com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration) NameExpr(com.github.javaparser.ast.expr.NameExpr) MethodReferenceExpr(com.github.javaparser.ast.expr.MethodReferenceExpr) ResolvedClassDeclaration(com.github.javaparser.resolution.declarations.ResolvedClassDeclaration) ResolvedVoidType(com.github.javaparser.resolution.types.ResolvedVoidType) FieldDeclaration(com.github.javaparser.ast.body.FieldDeclaration) SymbolReference(com.github.javaparser.symbolsolver.model.resolution.SymbolReference) ReflectionTypeSolver(com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver) IntegerLiteralExpr(com.github.javaparser.ast.expr.IntegerLiteralExpr) InferenceContext(com.github.javaparser.symbolsolver.logic.InferenceContext) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) BlockStmt(com.github.javaparser.ast.stmt.BlockStmt) ExpressionStmt(com.github.javaparser.ast.stmt.ExpressionStmt) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) MethodUsage(com.github.javaparser.resolution.MethodUsage) ReturnStmt(com.github.javaparser.ast.stmt.ReturnStmt) ResolvedVoidType(com.github.javaparser.resolution.types.ResolvedVoidType) ResolvedType(com.github.javaparser.resolution.types.ResolvedType)

Example 17 with LambdaExpr

use of com.github.javaparser.ast.expr.LambdaExpr in project javaparser by javaparser.

the class StatementContext method solveSymbol.

/**
 * Used where a symbol is being used (e.g. solving {@code x} when used as an argument {@code doubleThis(x)}, or calculation {@code return x * 2;}).
 * @param name the variable / reference / identifier used.
 * @param iterateAdjacentStmts flag to iterate adjacent statements, should be set to {@code true} except when calling itself in order to prevent revisiting already visited symbols.
 * @return // FIXME: Better documentation on how this is different to solveSymbolAsValue()
 */
private SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, boolean iterateAdjacentStmts) {
    /*
         * If we're in a variable declaration line.
         * Example: {@code double a=0, b=a;}
         * Example: {@code a instanceof String s;}
         */
    SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
    SymbolReference<? extends ResolvedValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
    if (symbolReference.isSolved()) {
        return symbolReference;
    }
    /*
         * If we're in a statement that contains a pattern expression.
         * Example: {@code double x = a instanceof String s;}
         */
    List<PatternExpr> patternExprs = patternExprsExposedFromChildren();
    for (int i = 0; i < patternExprs.size(); i++) {
        PatternExpr patternExpr = patternExprs.get(i);
        if (patternExpr.getNameAsString().equals(name)) {
            return SymbolReference.solved(JavaParserSymbolDeclaration.patternVar(patternExpr, typeSolver));
        }
    }
    Optional<Node> optionalParentNode = wrappedNode.getParentNode();
    if (!optionalParentNode.isPresent()) {
        return SymbolReference.unsolved(ResolvedValueDeclaration.class);
    }
    Node parentOfWrappedNode = optionalParentNode.get();
    // we should look in all the statements preceding, treating them as SymbolDeclarators
    if (parentOfWrappedNode instanceof MethodDeclaration) {
        return solveSymbolInParentContext(name);
    } else if (parentOfWrappedNode instanceof ConstructorDeclaration) {
        return solveSymbolInParentContext(name);
    } else if (parentOfWrappedNode instanceof LambdaExpr) {
        return solveSymbolInParentContext(name);
    } else if (parentOfWrappedNode instanceof NodeWithStatements) {
        // to prevent revisiting the same contexts over and over again.
        if (!iterateAdjacentStmts) {
            return SymbolReference.unsolved(ResolvedValueDeclaration.class);
        }
        NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) parentOfWrappedNode;
        // Assuming the wrapped node exists within the parent's collection of statements...
        int position = nodeWithStmt.getStatements().indexOf(wrappedNode);
        if (position == -1) {
            throw new IllegalStateException("This node is not a statement within the current NodeWithStatements");
        }
        // Start at the current node and work backwards...
        ListIterator<Statement> statementListIterator = nodeWithStmt.getStatements().listIterator(position);
        while (statementListIterator.hasPrevious()) {
            Context prevContext = JavaParserFactory.getContext(statementListIterator.previous(), typeSolver);
            if (prevContext instanceof StatementContext) {
                // We have an explicit check for "StatementContext" to prevent a factorial increase of visited statements.
                // 
                // For example consider the following:
                // String a = "a";
                // String b = "b";
                // String c = get();
                // 
                // If we simply call "prevContext.solveSymbol(name)" we will call the current method with the adjacent statement "prevContext".
                // Then "prevContext" will look at its previous adjacent statement. And so on and so forth.
                // When there are no more previous statements in this chain of method calls, we come back to here...
                // Then we look at the next "prevContext" which causes the entire process to start again.
                // This is how we get a factorial increase in calls to "solveSymbol".
                // 
                // So what we do instead with this check is we pass in a flag to say "Do not look at previous adjacent statements".
                // Since each visited "prevContext" does not look at its adjacent statements we only visit each statement once in this while loop.
                symbolReference = ((StatementContext<?>) prevContext).solveSymbol(name, false);
            } else {
                symbolReference = prevContext.solveSymbol(name);
            }
            if (symbolReference.isSolved()) {
                return symbolReference;
            }
        }
    }
    // If nothing is found, attempt to solve within the parent context
    return solveSymbolInParentContext(name);
}
Also used : Context(com.github.javaparser.symbolsolver.core.resolution.Context) SymbolDeclarator(com.github.javaparser.symbolsolver.resolution.SymbolDeclarator) PatternExpr(com.github.javaparser.ast.expr.PatternExpr) ResolvedMethodDeclaration(com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) NodeWithStatements(com.github.javaparser.ast.nodeTypes.NodeWithStatements) Node(com.github.javaparser.ast.Node) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) ListIterator(java.util.ListIterator) ConstructorDeclaration(com.github.javaparser.ast.body.ConstructorDeclaration) ResolvedValueDeclaration(com.github.javaparser.resolution.declarations.ResolvedValueDeclaration)

Example 18 with LambdaExpr

use of com.github.javaparser.ast.expr.LambdaExpr in project javaparser by javaparser.

the class StatementContext method solveSymbolAsValue.

@Override
public Optional<Value> solveSymbolAsValue(String name) {
    // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;)
    SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
    Optional<Value> symbolReference = solveWithAsValue(symbolDeclarator, name);
    if (symbolReference.isPresent()) {
        return symbolReference;
    }
    // If there is no parent
    if (!getParent().isPresent()) {
        return Optional.empty();
    }
    Context parentContext = getParent().get();
    Optional<Node> optionalParentNode = wrappedNode.getParentNode();
    if (!optionalParentNode.isPresent()) {
        return Optional.empty();
    }
    Node parentOfWrappedNode = optionalParentNode.get();
    // we should look in all the statements preceding, treating them as SymbolDeclarators
    if (parentOfWrappedNode instanceof MethodDeclaration) {
        return parentContext.solveSymbolAsValue(name);
    } else if (parentOfWrappedNode instanceof LambdaExpr) {
        return parentContext.solveSymbolAsValue(name);
    } else if (!(parentOfWrappedNode instanceof NodeWithStatements)) {
        return parentContext.solveSymbolAsValue(name);
    }
    NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) parentOfWrappedNode;
    int position = -1;
    // Get the position of the wrapped node.
    for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) {
        if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) {
            position = i;
        }
    }
    if (position == -1) {
        throw new RuntimeException();
    }
    // Working backwards from the node, try to solve the symbol. This limits the scope to declarations that appear prior to usage.
    for (int statementIndex = position - 1; statementIndex >= 0; statementIndex--) {
        Statement statement = nodeWithStmt.getStatements().get(statementIndex);
        symbolDeclarator = JavaParserFactory.getSymbolDeclarator(statement, typeSolver);
        symbolReference = solveWithAsValue(symbolDeclarator, name);
        if (symbolReference.isPresent()) {
            return symbolReference;
        }
    }
    // If nothing is found we should ask the parent context.
    return solveSymbolAsValueInParentContext(name);
}
Also used : Context(com.github.javaparser.symbolsolver.core.resolution.Context) SymbolDeclarator(com.github.javaparser.symbolsolver.resolution.SymbolDeclarator) ResolvedMethodDeclaration(com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) NodeWithStatements(com.github.javaparser.ast.nodeTypes.NodeWithStatements) Statement(com.github.javaparser.ast.stmt.Statement) Node(com.github.javaparser.ast.Node) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) Value(com.github.javaparser.symbolsolver.model.resolution.Value)

Example 19 with LambdaExpr

use of com.github.javaparser.ast.expr.LambdaExpr in project javaparser by javaparser.

the class Issue186Test method lambdaPrimitivesIssue.

@Test
void lambdaPrimitivesIssue() {
    CompilationUnit cu = parseSample("Issue186");
    ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
    MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "bar");
    List<LambdaExpr> lambdas = methodDeclaration.findAll(LambdaExpr.class);
    TypeSolver typeSolver = new ReflectionTypeSolver();
    JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
    assertEquals("java.util.function.Predicate<? super java.lang.String>", javaParserFacade.getType(lambdas.get(0)).describe());
    assertEquals("java.util.function.Function<? super java.lang.String, ? extends java.lang.Integer>", javaParserFacade.getType(lambdas.get(1)).describe());
    assertEquals("java.util.function.Predicate<? super java.lang.Integer>", javaParserFacade.getType(lambdas.get(2)).describe());
}
Also used : CompilationUnit(com.github.javaparser.ast.CompilationUnit) ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) TypeSolver(com.github.javaparser.symbolsolver.model.resolution.TypeSolver) ReflectionTypeSolver(com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) JavaParserFacade(com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade) ReflectionTypeSolver(com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver) AbstractResolutionTest(com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest) Test(org.junit.jupiter.api.Test)

Example 20 with LambdaExpr

use of com.github.javaparser.ast.expr.LambdaExpr in project javaparser by javaparser.

the class LambdaResolutionTest method typeOfVoidLambda.

@Test
void typeOfVoidLambda() {
    CompilationUnit cu = parseSample("LambdaVoid");
    com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
    MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaEmpty");
    ReturnStmt returnStmt = Navigator.demandReturnStmt(method);
    Expression expression = returnStmt.getExpression().get();
    LambdaExpr lambdaExpr = Navigator.demandNodeOfGivenClass(expression, LambdaExpr.class);
    JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
    ResolvedType type = javaParserFacade.getType(lambdaExpr);
    assertEquals("java.util.function.Consumer<? super java.lang.String>", type.describe());
}
Also used : CompilationUnit(com.github.javaparser.ast.CompilationUnit) Expression(com.github.javaparser.ast.expr.Expression) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) LambdaExpr(com.github.javaparser.ast.expr.LambdaExpr) JavaParserFacade(com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade) ReflectionTypeSolver(com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver) ReturnStmt(com.github.javaparser.ast.stmt.ReturnStmt) ResolvedType(com.github.javaparser.resolution.types.ResolvedType) Test(org.junit.jupiter.api.Test)

Aggregations

LambdaExpr (com.github.javaparser.ast.expr.LambdaExpr)69 Parameter (com.github.javaparser.ast.body.Parameter)36 NameExpr (com.github.javaparser.ast.expr.NameExpr)29 MethodCallExpr (com.github.javaparser.ast.expr.MethodCallExpr)28 Expression (com.github.javaparser.ast.expr.Expression)26 BlockStmt (com.github.javaparser.ast.stmt.BlockStmt)25 UnknownType (com.github.javaparser.ast.type.UnknownType)23 StringLiteralExpr (com.github.javaparser.ast.expr.StringLiteralExpr)18 ExpressionStmt (com.github.javaparser.ast.stmt.ExpressionStmt)17 ReturnStmt (com.github.javaparser.ast.stmt.ReturnStmt)16 CompilationUnit (com.github.javaparser.ast.CompilationUnit)11 ClassOrInterfaceType (com.github.javaparser.ast.type.ClassOrInterfaceType)11 MethodDeclaration (com.github.javaparser.ast.body.MethodDeclaration)10 VariableDeclarator (com.github.javaparser.ast.body.VariableDeclarator)10 LongLiteralExpr (com.github.javaparser.ast.expr.LongLiteralExpr)10 NullLiteralExpr (com.github.javaparser.ast.expr.NullLiteralExpr)10 Test (org.junit.jupiter.api.Test)10 Node (com.github.javaparser.ast.Node)8 CastExpr (com.github.javaparser.ast.expr.CastExpr)8 ObjectCreationExpr (com.github.javaparser.ast.expr.ObjectCreationExpr)8