blob: deeeee1458fd4205ea15de52e311a3f8a96549c6 [file] [log] [blame]
/*
* Copyright 2016 Federico Tomassetti
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.javaparser.symbolsolver.resolution;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.ThisExpr;
import com.github.javaparser.ast.stmt.ExpressionStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.resolution.MethodUsage;
import com.github.javaparser.resolution.types.ResolvedReferenceType;
import com.github.javaparser.resolution.types.ResolvedType;
import com.github.javaparser.symbolsolver.javaparser.Navigator;
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.model.resolution.Value;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Tests related to resolved Generics types.
*/
class GenericsResolutionTest extends AbstractResolutionTest {
@Test
void resolveFieldWithGenericTypeToString() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
VariableDeclarator fieldS = Navigator.demandField(clazz, "s");
SymbolSolver symbolSolver = new SymbolSolver(new ReflectionTypeSolver());
Optional<Value> symbolReference = symbolSolver.solveSymbolAsValue("s", fieldS);
assertEquals(true, symbolReference.isPresent());
assertEquals("s", symbolReference.get().getName());
ResolvedType type = symbolReference.get().getType();
assertEquals(1, type.asReferenceType().typeParametersValues().size());
assertEquals("java.lang.String", type.asReferenceType().typeParametersValues().get(0).describe());
}
@Test
void resolveFieldWithGenericTypeToDeclaredClass() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
VariableDeclarator fieldS = Navigator.demandField(clazz, "g");
SymbolSolver symbolSolver = new SymbolSolver(new ReflectionTypeSolver());
Optional<Value> symbolReference = symbolSolver.solveSymbolAsValue("g", fieldS);
assertEquals(true, symbolReference.isPresent());
assertEquals("g", symbolReference.get().getName());
ResolvedType type = symbolReference.get().getType();
assertEquals(1, type.asReferenceType().typeParametersValues().size());
assertEquals("me.tomassetti.symbolsolver.javaparser.Generics", type.asReferenceType().typeParametersValues().get(0).describe());
}
@Test
void resolveFieldWithGenericTypeToInteger() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
VariableDeclarator fieldS = Navigator.demandField(clazz, "i");
SymbolSolver symbolSolver = new SymbolSolver(new ReflectionTypeSolver());
Optional<Value> symbolReference = symbolSolver.solveSymbolAsValue("i", fieldS);
assertEquals(true, symbolReference.isPresent());
assertEquals("i", symbolReference.get().getName());
ResolvedType type = symbolReference.get().getType();
assertEquals(1, type.asReferenceType().typeParametersValues().size());
assertEquals("java.lang.Integer", type.asReferenceType().typeParametersValues().get(0).describe());
}
@Test
void resolveFieldOfVariableType() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
VariableDeclarator field = Navigator.demandField(clazz, "a");
SymbolSolver symbolSolver = new SymbolSolver(new ReflectionTypeSolver());
Optional<Value> symbolReference = symbolSolver.solveSymbolAsValue("a", field);
assertEquals(true, symbolReference.isPresent());
assertEquals("a", symbolReference.get().getName());
ResolvedType type = symbolReference.get().getType();
assertEquals(true, type.isTypeVariable());
assertEquals("A", type.describe());
}
@Test
void resolveFieldOfGenericReferringToVariableType() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
VariableDeclarator field = Navigator.demandField(clazz, "as");
SymbolSolver symbolSolver = new SymbolSolver(new ReflectionTypeSolver());
Optional<Value> symbolReference = symbolSolver.solveSymbolAsValue("as", field);
assertEquals(true, symbolReference.isPresent());
assertEquals("as", symbolReference.get().getName());
ResolvedType type = symbolReference.get().getType();
assertEquals(false, type.isTypeVariable());
assertEquals("java.util.List<A>", type.describe());
assertEquals(1, type.asReferenceType().typeParametersValues().size());
ResolvedType typeParam = type.asReferenceType().typeParametersValues().get(0);
assertEquals(true, typeParam.isTypeVariable());
assertEquals("A", typeParam.describe());
}
@Test
void resolveUsageOfGenericFieldSimpleCase() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
MethodDeclaration method = Navigator.demandMethod(clazz, "foo1");
ExpressionStmt stmt = (ExpressionStmt) method.getBody().get().getStatements().get(0);
Expression expression = stmt.getExpression();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
assertEquals(false, type.isTypeVariable());
assertEquals("java.lang.String", type.describe());
}
//PRIMA UN TEST CHE DICA CHE IL TIPO DEL CAMPO AS e' LIST<A> NON LIST<E>
@Test
void resolveUsageOfGenericFieldIntermediateCase() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
VariableDeclarator field = Navigator.demandField(clazz, "as");
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(field);
assertEquals(false, type.isTypeVariable());
assertEquals("java.util.List<A>", type.describe());
assertEquals(1, type.asReferenceType().typeParametersValues().size());
assertEquals(true, type.asReferenceType().typeParametersValues().get(0).isTypeVariable());
assertEquals("A", type.asReferenceType().typeParametersValues().get(0).describe());
}
@Test
void resolveUsageOfGenericFieldAdvancedCase() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
MethodDeclaration method = Navigator.demandMethod(clazz, "foo2");
ExpressionStmt stmt = (ExpressionStmt) method.getBody().get().getStatements().get(0);
Expression expression = stmt.getExpression();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
assertEquals(false, type.isTypeVariable());
assertEquals("java.util.List<java.lang.String>", type.describe());
assertEquals(1, type.asReferenceType().typeParametersValues().size());
assertEquals(false, type.asReferenceType().typeParametersValues().get(0).isTypeVariable());
assertEquals("java.lang.String", type.asReferenceType().typeParametersValues().get(0).describe());
}
@Test
void resolveUsageOfMethodOfGenericClass() {
CompilationUnit cu = parseSample("Generics");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericMethodCalls.Derived");
MethodDeclaration method = Navigator.demandMethod(clazz, "caller");
MethodCallExpr expression = Navigator.findMethodCall(method, "callee").get();
MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(expression);
assertEquals("callee", methodUsage.getName());
}
@Test
void resolveUsageOfMethodOfGenericClassWithUnboundedWildcard() {
CompilationUnit cu = parseSample("GenericsWildcard");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericsWildcard");
MethodDeclaration method = Navigator.demandMethod(clazz, "unbounded");
MethodCallExpr expression = Navigator.findMethodCall(method, "toString").get();
MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(expression);
assertEquals("toString", methodUsage.getName());
assertEquals("java.lang.Object", methodUsage.declaringType().getQualifiedName());
}
@Test
void resolveUsageOfMethodOfGenericClassWithExtendsWildcard() {
CompilationUnit cu = parseSample("GenericsWildcard");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericsWildcard");
MethodDeclaration method = Navigator.demandMethod(clazz, "bounded");
MethodCallExpr expression = Navigator.findMethodCall(method, "bar").get();
MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(expression);
assertEquals("bar", methodUsage.getName());
assertEquals("GenericsWildcard.Foo", methodUsage.declaringType().getQualifiedName());
}
@Test
void resolveElementOfList() {
CompilationUnit cu = parseSample("ElementOfList");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ElementOfList");
MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
VariableDeclarator variableDeclarator = Navigator.demandVariableDeclaration(method, "a").get();
Expression expression = variableDeclarator.getInitializer().get();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
assertEquals(false, type.isTypeVariable());
assertEquals("Comment", type.describe());
}
@Test
void resolveElementOfListAdvancedExample() {
CompilationUnit cu = parseSample("ElementOfList");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ElementOfList");
MethodDeclaration method = Navigator.demandMethod(clazz, "annotations");
VariableDeclarator variableDeclarator = Navigator.demandVariableDeclaration(method, "a").get();
Expression expression = variableDeclarator.getInitializer().get();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
assertEquals(false, type.isTypeVariable());
assertEquals("AnnotationExpr", type.describe());
}
@Test
void genericsInheritance() {
CompilationUnit cu = parseSample("MethodTypeParams");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "VoidVisitorAdapter");
MethodDeclaration method = Navigator.demandMethod(clazz, "visit");
MethodCallExpr call = Navigator.findMethodCall(method, "accept").get();
Expression thisRef = call.getArguments().get(0);
TypeSolver typeSolver = new ReflectionTypeSolver();
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
ResolvedType voidVisitorAdapterOfA = javaParserFacade.getType(thisRef);
List<ResolvedReferenceType> allAncestors = voidVisitorAdapterOfA.asReferenceType().getAllAncestors();
assertEquals(2, allAncestors.size());
}
@Test
void methodTypeParams() {
CompilationUnit cu = parseSample("MethodTypeParams");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "VoidVisitorAdapter");
MethodDeclaration method = Navigator.demandMethod(clazz, "visit");
MethodCallExpr call = Navigator.findMethodCall(method, "accept").get();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(call);
assertEquals(false, type.isTypeVariable());
assertEquals("void", type.describe());
}
@Test
void classCastScope() {
CompilationUnit cu = parseSample("ClassCast");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassCast");
MethodDeclaration method = Navigator.demandMethod(clazz, "getNodesByType");
MethodCallExpr call = Navigator.findMethodCall(method, "cast").get();
TypeSolver typeSolver = new ReflectionTypeSolver();
Expression scope = call.getScope().get();
ResolvedType type = JavaParserFacade.get(typeSolver).getType(scope);
//System.out.println(typeUsage);
assertEquals(false, type.isTypeVariable());
assertEquals("java.lang.Class<N>", type.describe());
}
@Test
void classCast() {
CompilationUnit cu = parseSample("ClassCast");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassCast");
MethodDeclaration method = Navigator.demandMethod(clazz, "getNodesByType");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(returnStmt.getExpression().get());
assertEquals(true, type.isTypeVariable());
assertEquals("N", type.describe());
}
@Test
void typeParamOnReturnTypeStep1() {
CompilationUnit cu = parseSample("TypeParamOnReturnType");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
ThisExpr thisExpr = Navigator.findNodeOfGivenClass(method, ThisExpr.class);
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(thisExpr);
assertEquals(false, type.isTypeVariable());
assertEquals("TypeParamOnReturnType", type.describe());
}
@Test
void typeParamOnReturnTypeStep2() {
CompilationUnit cu = parseSample("TypeParamOnReturnType");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
NameExpr n1 = Navigator.findNameExpression(method, "n1").get();
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(n1);
assertEquals(true, type.isTypeVariable());
assertEquals("T", type.describe());
}
@Test
void typeParamOnReturnTypeStep3() {
CompilationUnit cu = parseSample("TypeParamOnReturnType");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
MethodCallExpr call = Navigator.findMethodCall(method, "accept").get();
JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
ResolvedType type = javaParserFacade.getType(call);
assertEquals(false, type.isTypeVariable());
assertEquals("java.lang.Boolean", type.describe());
}
@Test
void typeParamOnReturnType() {
CompilationUnit cu = parseSample("TypeParamOnReturnType");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(returnStmt.getExpression().get());
assertEquals(false, type.isTypeVariable());
assertEquals("boolean", type.describe());
}
/*@Test
public void genericCollectionWithWildcardsAndExtensionsPrep() {
CompilationUnit cu = parseSample("GenericCollectionWithExtension");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
TypeSolver typeSolver = new JreTypeSolver();
MethodCallExpr call = (MethodCallExpr) returnStmt.getExpr();
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
List<TypeUsage> params = new ArrayList<>();
if (call.getArgs() != null) {
for (Expression param : call.getArgs()) {
params.add(javaParserFacade.getType(param, false));
}
}
Context context = JavaParserFactory.getContext(call, typeSolver);
ReferenceTypeUsage typeOfScope = javaParserFacade.getType(call.getScope()).asReferenceType();
me.tomassetti.symbolsolver.model.declarations.TypeDeclaration typeDeclaration = typeOfScope.getTypeDeclaration();
List<TypeUsage> typeParametersValues = typeOfScope.typeParametersValues();
List<MethodUsage> methods = new ArrayList<>();
for (Method m : List.class.getMethods()) {
if (m.getName().equals("addAll") && !m.isBridge() && !m.isSynthetic()) {
me.tomassetti.symbolsolver.model.declarations.MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(m, typeSolver);
if (methods.size() == 0) {
// ok, e' il primo
ReferenceTypeUsage paramType = methodDeclaration.getParam(0).getType(typeSolver).asReferenceType();
assertTrue(paramType.asReferenceType().typeParametersValues().get(0).isWildcard());
}
MethodUsage mu = new MethodUsage(methodDeclaration, typeSolver);
int i = 0;
for (TypeParameter tp : typeDeclaration.getTypeParameters()) {
mu = mu.replaceTypeParameter(tp.getName(), typeParametersValues.get(i));
i++;
}
methods.add(mu);
}
}
assertTrue(MethodResolutionLogic.isApplicable(methods.get(0), "addAll", params, typeSolver));
//Optional<MethodUsage> methodUsage = MethodResolutionLogic.findMostApplicableUsage(methods, "addAll", params, typeSolver);
//Optional<MethodUsage> methodUsage = typeDeclaration.solveMethodAsUsage("addAll", params, typeSolver, context, typeParametersValues);
//Optional<MethodUsage> methodUsage = context.solveMethodAsUsage("addAll", params, typeSolver);
//assertTrue(methodUsage.isPresent());
}*/
@Test
void genericCollectionWithWildcardsAndExtensions() {
CompilationUnit cu = parseSample("GenericCollectionWithExtension");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
TypeSolver typeSolver = new ReflectionTypeSolver();
Expression returnStmtExpr = returnStmt.getExpression().get();
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
ResolvedType type = javaParserFacade.getType(returnStmtExpr);
assertEquals(false, type.isTypeVariable());
assertEquals("boolean", type.describe());
}
@Test
void methodWithGenericParameterTypes() {
CompilationUnit cu = parseSample("GenericCollectionWithExtension");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
MethodCallExpr methodCall = Navigator.findMethodCall(method, "foo").get();
TypeSolver typeSolver = new ReflectionTypeSolver();
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
MethodUsage methodUsage = javaParserFacade.solveMethodAsUsage(methodCall);
assertEquals("foo", methodUsage.getName());
}
@Test
void genericCollectionWithWildcards() {
CompilationUnit cu = parseSample("GenericCollection");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
TypeSolver typeSolver = new ReflectionTypeSolver();
Expression returnStmtExpr = returnStmt.getExpression().get();
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
ResolvedType type = javaParserFacade.getType(returnStmtExpr);
assertEquals(false, type.isTypeVariable());
assertEquals("boolean", type.describe());
}
}