use of com.github.javaparser.resolution.MethodUsage in project javaparser by javaparser.
the class StatementContextResolutionTest method resolveMethodOnGenericClass.
@Test
public void resolveMethodOnGenericClass() {
CompilationUnit cu = parseSample("LocalVariableInParent");
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo5");
MethodCallExpr call = Navigator.findMethodCall(method, "add").get();
TypeSolver typeSolver = new ReflectionTypeSolver();
SymbolReference<? extends ResolvedValueDeclaration> ref = JavaParserFacade.get(typeSolver).solve(call.getScope().get());
assertTrue(ref.isSolved());
assertEquals("java.util.List<Comment>", ref.getCorrespondingDeclaration().getType().describe());
MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
assertEquals("add", methodUsage.getName());
}
use of com.github.javaparser.resolution.MethodUsage in project javaparser by javaparser.
the class MethodCallExprContextResolutionTest method assertCanSolveGenericMethodCallMustUseProvidedTypeArgs.
private void assertCanSolveGenericMethodCallMustUseProvidedTypeArgs(String callMethodName) {
MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
CombinedTypeSolver typeSolver = createTypeSolver();
MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, Collections.emptyList(), typeSolver);
assertTrue(ref.isPresent());
assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
assertEquals(Collections.singletonList("java.lang.Integer"), ref.get().typeParametersMap().getTypes().stream().map(ty -> ty.asReferenceType().describe()).collect(Collectors.toList()));
}
use of com.github.javaparser.resolution.MethodUsage in project javaparser by javaparser.
the class TypeExtractor method visit.
@Override
public ResolvedType visit(MethodReferenceExpr node, Boolean solveLambdas) {
if (requireParentNode(node) instanceof MethodCallExpr) {
MethodCallExpr callExpr = (MethodCallExpr) requireParentNode(node);
int pos = JavaParserSymbolDeclaration.getParamPos(node);
SymbolReference<ResolvedMethodDeclaration> refMethod = facade.solve(callExpr, false);
if (!refMethod.isSolved()) {
throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId());
}
logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName());
// logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
if (solveLambdas) {
MethodUsage usage = facade.solveMethodAsUsage(callExpr);
ResolvedType result = usage.getParamType(pos);
// We need to replace the type variables
Context ctx = JavaParserFactory.getContext(node, typeSolver);
result = solveGenericTypes(result, ctx, typeSolver);
// lambdas
if (FunctionalInterfaceLogic.getFunctionalMethod(result).isPresent()) {
MethodReferenceExpr methodReferenceExpr = node;
ResolvedType actualType = facade.toMethodUsage(methodReferenceExpr).returnType();
ResolvedType formalType = FunctionalInterfaceLogic.getFunctionalMethod(result).get().returnType();
InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
inferenceContext.addPair(formalType, actualType);
result = inferenceContext.resolve(inferenceContext.addSingle(result));
}
return result;
}
return refMethod.getCorrespondingDeclaration().getParam(pos).getType();
}
throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value");
}
use of com.github.javaparser.resolution.MethodUsage 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.resolution.MethodUsage in project javaparser by javaparser.
the class TypeExtractor method visit.
@Override
public ResolvedType visit(MethodCallExpr node, Boolean solveLambdas) {
logger.finest("getType on method call " + node);
// first solve the method
MethodUsage ref = facade.solveMethodAsUsage(node);
logger.finest("getType on method call " + node + " resolved to " + ref);
logger.finest("getType on method call " + node + " return type is " + ref.returnType());
return ref.returnType();
// the type is the return type of the method
}
Aggregations