use of com.github.javaparser.symbolsolver.model.resolution.Value in project javaparser by javaparser.
the class LambdaExprContextResolutionTest method solveParameterOfLambdaInFieldDecl.
@Test
public void solveParameterOfLambdaInFieldDecl() {
CompilationUnit cu = parseSample("Lambda");
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
VariableDeclarator field = Navigator.demandField(clazz, "functional");
LambdaExpr lambdaExpr = (LambdaExpr) field.getInitializer().get();
File src = new File("src/test/resources");
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new ReflectionTypeSolver());
combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(src)));
Context context = new LambdaExprContext(lambdaExpr, combinedTypeSolver);
Optional<Value> ref = context.solveSymbolAsValue("p", typeSolver);
assertTrue(ref.isPresent());
assertEquals("java.lang.String", ref.get().getType().describe());
}
use of com.github.javaparser.symbolsolver.model.resolution.Value in project javaparser by javaparser.
the class LambdaExprContextResolutionTest method solveParameterOfLambdaInVarDecl.
@Test
public void solveParameterOfLambdaInVarDecl() {
CompilationUnit cu = parseSample("Lambda");
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
MethodDeclaration method = Navigator.demandMethod(clazz, "testFunctionalVar");
VariableDeclarator varDecl = Navigator.demandVariableDeclaration(method, "a").get();
LambdaExpr lambdaExpr = (LambdaExpr) varDecl.getInitializer().get();
File src = adaptPath(new File("src/test/resources"));
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new ReflectionTypeSolver());
combinedTypeSolver.add(new JavaParserTypeSolver(src));
Context context = new LambdaExprContext(lambdaExpr, combinedTypeSolver);
Optional<Value> ref = context.solveSymbolAsValue("p", typeSolver);
assertTrue(ref.isPresent());
assertEquals("java.lang.String", ref.get().getType().describe());
}
use of com.github.javaparser.symbolsolver.model.resolution.Value in project javaparser by javaparser.
the class TypeExtractor method visit.
@Override
public ResolvedType visit(NameExpr node, Boolean solveLambdas) {
logger.finest("getType on name expr " + node);
Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node);
if (!value.isPresent()) {
throw new com.github.javaparser.resolution.UnsolvedSymbolException("Solving " + node, node.getName().getId());
} else {
return value.get().getType();
}
}
use of com.github.javaparser.symbolsolver.model.resolution.Value in project javaparser by javaparser.
the class TypeExtractor method visit.
@Override
public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) {
if (requireParentNode(node) instanceof MethodCallExpr) {
MethodCallExpr callExpr = (MethodCallExpr) requireParentNode(node);
int pos = JavaParserSymbolDeclaration.getParamPos(node);
SymbolReference<ResolvedMethodDeclaration> refMethod = facade.solve(callExpr);
if (!refMethod.isSolved()) {
throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId());
}
logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
if (solveLambdas) {
// The type parameter referred here should be the java.util.stream.Stream.T
ResolvedType result = refMethod.getCorrespondingDeclaration().getParam(pos).getType();
if (callExpr.getScope().isPresent()) {
Expression scope = callExpr.getScope().get();
// If it is a static call we should not try to get the type of the scope
boolean staticCall = false;
if (scope instanceof NameExpr) {
NameExpr nameExpr = (NameExpr) scope;
try {
SymbolReference<ResolvedTypeDeclaration> type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver);
if (type.isSolved()) {
staticCall = true;
}
} catch (Exception e) {
}
}
if (!staticCall) {
ResolvedType scopeType = facade.getType(scope);
if (scopeType.isReferenceType()) {
result = scopeType.asReferenceType().useThisTypeParametersOnTheGivenType(result);
}
}
}
// We need to replace the type variables
Context ctx = JavaParserFactory.getContext(node, typeSolver);
result = solveGenericTypes(result, ctx, typeSolver);
// 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 {
return 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;
} else {
return refMethod.getCorrespondingDeclaration().getParam(pos).getType();
}
} else {
throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
}
}
use of com.github.javaparser.symbolsolver.model.resolution.Value in project javaparser by javaparser.
the class AbstractMethodLikeDeclarationContext method solveSymbolAsValue.
@Override
public final Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
for (Parameter parameter : wrappedNode.getParameters()) {
SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
Optional<Value> symbolReference = solveWithAsValue(sb, name, typeSolver);
if (symbolReference.isPresent()) {
// Perform parameter type substitution as needed
return symbolReference;
}
}
// if nothing is found we should ask the parent context
return getParent().solveSymbolAsValue(name, typeSolver);
}
Aggregations