MethodCallExprContextResolutionTest.java
/*
* Copyright (C) 2015-2016 Federico Tomassetti
* Copyright (C) 2017-2024 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.resolution.Context;
import com.github.javaparser.resolution.MethodUsage;
import com.github.javaparser.resolution.Navigator;
import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
import com.github.javaparser.resolution.model.typesystem.ReferenceTypeImpl;
import com.github.javaparser.resolution.types.ResolvedType;
import com.github.javaparser.resolution.types.ResolvedVoidType;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.javaparsermodel.contexts.MethodCallExprContext;
import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ClassLoaderTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
/**
* @author Malte Langkabel
*/
class MethodCallExprContextResolutionTest extends AbstractResolutionTest {
private MethodCallExpr getMethodCallExpr(String methodName, String callingMethodName) {
CompilationUnit cu = parseSample("MethodCalls");
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
MethodDeclaration method = Navigator.demandMethod(clazz, methodName);
return Navigator.findMethodCall(method, callingMethodName).get();
}
private CombinedTypeSolver createTypeSolver() {
Path src = adaptPath("src/test/resources");
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new ReflectionTypeSolver());
combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
return combinedTypeSolver;
}
@Test
void solveNestedMethodCallExprContextWithoutScope() {
MethodCallExpr methodCallExpr = getMethodCallExpr("bar1", "foo");
CombinedTypeSolver typeSolver = createTypeSolver();
Context context = new MethodCallExprContext(methodCallExpr, typeSolver);
Optional<MethodUsage> ref = context.solveMethodAsUsage("foo", Collections.emptyList());
assertTrue(ref.isPresent());
assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
}
@Test
void solveGenericMethodCallMustUseProvidedTypeArgs() {
assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("genericMethod0");
}
@Test
void solveStaticGenericMethodCallMustUseProvidedTypeArgs() {
assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("staticGenericMethod0");
}
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());
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()));
}
@Test
void solveGenericMethodCallCanInferFromArguments() {
assertCanSolveGenericMethodCallCanInferFromArguments("genericMethod1");
}
@Test
void solveStaticGenericMethodCallCanInferFromArguments() {
assertCanSolveGenericMethodCallCanInferFromArguments("staticGenericMethod1");
}
private void assertCanSolveGenericMethodCallCanInferFromArguments(String callMethodName) {
MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
CombinedTypeSolver typeSolver = createTypeSolver();
MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
ResolvedReferenceTypeDeclaration stringType = typeSolver.solveType("java.lang.String");
List<ResolvedType> argumentsTypes = new ArrayList<>();
argumentsTypes.add(new ReferenceTypeImpl(stringType));
Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, argumentsTypes);
assertTrue(ref.isPresent());
assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
assertEquals(
Collections.singletonList("java.lang.String"),
ref.get().typeParametersMap().getTypes().stream()
.map(ty -> ty.asReferenceType().describe())
.collect(Collectors.toList()));
}
@Test
public void test() {
ParserConfiguration config =
new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(createTypeSolver()));
StaticJavaParser.setConfiguration(config);
CompilationUnit cu = parseSample("Issue2258");
List<MethodCallExpr> expressions = cu.getChildNodesByType(MethodCallExpr.class);
assertEquals(2, expressions.size());
ResolvedType r = expressions.get(1).calculateResolvedType();
assertTrue(ResolvedVoidType.class.isAssignableFrom(r.getClass()));
}
@Test
public void testGenericParameter() {
ParserConfiguration config =
new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(createTypeSolver()));
StaticJavaParser.setConfiguration(config);
CompilationUnit cu = parseSample("ISSUES_Generic_Parameter");
List<MethodCallExpr> expressions = cu.getChildNodesByType(MethodCallExpr.class);
assertEquals(1, expressions.size());
ResolvedType r = expressions.get(0).calculateResolvedType();
assertTrue(ReferenceTypeImpl.class.isAssignableFrom(r.getClass()));
}
@Test
public void testResolveChainedCallOnReflectionType() throws Exception {
Path pathToJar = adaptPath("src/test/resources/issue2667/jsonobject.jar");
CombinedTypeSolver typeSolver = createTypeSolver();
typeSolver.add(new ClassLoaderTypeSolver(
new URLClassLoader(new URL[] {pathToJar.toUri().toURL()})));
ParserConfiguration config = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
StaticJavaParser.setConfiguration(config);
CompilationUnit cu = parseSample("Issue2667");
Set<MethodCallExpr> methodCallExpr = new HashSet<>(cu.findAll(MethodCallExpr.class));
int errorCount = 0;
for (MethodCallExpr expr : methodCallExpr) {
try {
ResolvedMethodDeclaration rd = expr.resolve();
} catch (UnsolvedSymbolException e) {
errorCount++;
}
}
assertEquals(0, errorCount, "Expected zero UnsolvedSymbolException s");
}
@Test
void solveVariadicStaticGenericMethodCallCanInferFromArguments() {
ParserConfiguration config =
new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(createTypeSolver()));
StaticJavaParser.setConfiguration(config);
MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", "variadicStaticGenericMethod");
ResolvedType resolvedType = methodCallExpr.calculateResolvedType();
assertEquals("java.lang.String", resolvedType.describe());
}
// Related to issue #3195
@Test
void solveVariadicStaticGenericMethodCallCanInferFromArguments2() {
ParserConfiguration config =
new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(createTypeSolver()));
StaticJavaParser.setConfiguration(config);
MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", "asList");
ResolvedType resolvedType = methodCallExpr.calculateResolvedType();
assertEquals("java.util.List<java.lang.String>", resolvedType.describe());
}
}