wip
diff --git a/src/main/java/me/tomassetti/symbolsolver/model/typesystem/TypeUsage.java b/src/main/java/me/tomassetti/symbolsolver/model/typesystem/TypeUsage.java
index df65c4f..f1ed9c4 100644
--- a/src/main/java/me/tomassetti/symbolsolver/model/typesystem/TypeUsage.java
+++ b/src/main/java/me/tomassetti/symbolsolver/model/typesystem/TypeUsage.java
@@ -84,6 +84,10 @@
throw new UnsupportedOperationException(this.getClass().getCanonicalName());
}
+ default WildcardUsage asWildcard() {
+ throw new UnsupportedOperationException(this.getClass().getCanonicalName());
+ }
+
///
/// Naming
///
diff --git a/src/main/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsage.java b/src/main/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsage.java
index 81838b9..f25c279 100644
--- a/src/main/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsage.java
+++ b/src/main/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsage.java
@@ -1,14 +1,10 @@
package me.tomassetti.symbolsolver.model.typesystem;
-import com.github.javaparser.ast.type.WildcardType;
-
-import java.util.List;
-
public class WildcardUsage implements TypeUsage {
//private WildcardType type;
private BoundType type;
- private ReferenceTypeUsage boundedType;
+ private TypeUsage boundedType;
public enum BoundType {
SUPER,
@@ -21,15 +17,19 @@
public static WildcardUsage UNBOUNDED = new WildcardUsage(null, null);
- public static WildcardUsage superBound(ReferenceTypeUsage typeUsage) {
+ public static WildcardUsage superBound(TypeUsage typeUsage) {
return new WildcardUsage(BoundType.SUPER, typeUsage);
}
- public static WildcardUsage extendsBound(ReferenceTypeUsage typeUsage) {
+ public static WildcardUsage extendsBound(TypeUsage typeUsage) {
return new WildcardUsage(BoundType.EXTENDS, typeUsage);
}
- private WildcardUsage(BoundType type, ReferenceTypeUsage boundedType) {
+ public WildcardUsage asWildcard() {
+ return this;
+ }
+
+ private WildcardUsage(BoundType type, TypeUsage boundedType) {
this.type = type;
this.boundedType = boundedType;
}
@@ -75,7 +75,7 @@
return type == BoundType.EXTENDS;
}
- public ReferenceTypeUsage getBoundedType() {
+ public TypeUsage getBoundedType() {
if (boundedType == null) {
throw new IllegalStateException();
}
@@ -87,4 +87,16 @@
throw new UnsupportedOperationException();
}
+ @Override
+ public TypeUsage replaceParam(String name, TypeUsage replaced) {
+ if (boundedType == null) {
+ return this;
+ }
+ TypeUsage boundedTypeReplaced = boundedType.replaceParam(name, replaced);
+ if (boundedTypeReplaced != boundedType) {
+ return new WildcardUsage(type, boundedTypeReplaced);
+ } else {
+ return this;
+ }
+ }
}
diff --git a/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java b/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
index fff1863..f43b849 100644
--- a/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
+++ b/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
@@ -13,6 +13,7 @@
import me.tomassetti.symbolsolver.resolution.javaparser.UnsolvedSymbolException;
import me.tomassetti.symbolsolver.model.invokations.MethodUsage;
import me.tomassetti.symbolsolver.model.typesystem.TypeUsage;
+import me.tomassetti.symbolsolver.resolution.reflection.ReflectionClassDeclaration;
import java.util.List;
import java.util.Optional;
@@ -128,7 +129,15 @@
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
if (wrappedNode.getScope() != null) {
TypeUsage typeOfScope = JavaParserFacade.get(typeSolver).getType(wrappedNode.getScope());
- return typeOfScope.asReferenceTypeUsage().solveMethod(name, parameterTypes, typeSolver);
+ if (typeOfScope.isWildcard()) {
+ if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) {
+ return typeOfScope.asWildcard().getBoundedType().asReferenceTypeUsage().solveMethod(name, parameterTypes, typeSolver);
+ } else {
+ return new ReferenceTypeUsage(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver).solveMethod(name, parameterTypes, typeSolver);
+ }
+ } else {
+ return typeOfScope.asReferenceTypeUsage().solveMethod(name, parameterTypes, typeSolver);
+ }
} else {
TypeUsage typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode);
return typeOfScope.asReferenceTypeUsage().solveMethod(name, parameterTypes, typeSolver);
diff --git a/src/main/java/me/tomassetti/symbolsolver/resolution/reflection/ReflectionFactory.java b/src/main/java/me/tomassetti/symbolsolver/resolution/reflection/ReflectionFactory.java
index 2737280..c04e9ac 100644
--- a/src/main/java/me/tomassetti/symbolsolver/resolution/reflection/ReflectionFactory.java
+++ b/src/main/java/me/tomassetti/symbolsolver/resolution/reflection/ReflectionFactory.java
@@ -3,10 +3,7 @@
import me.tomassetti.symbolsolver.model.typesystem.*;
import me.tomassetti.symbolsolver.resolution.TypeSolver;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
+import java.lang.reflect.*;
/**
* Created by federico on 02/08/15.
@@ -36,8 +33,13 @@
return new TypeParameterUsage(typeParameter);
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
- // TODO deal with type parameters
- return typeUsageFor(pt.getRawType(), typeSolver);
+ ReferenceTypeUsage rawType = typeUsageFor(pt.getRawType(), typeSolver).asReferenceTypeUsage();
+ int i=0;
+ for (Type actualTypeArgument : pt.getActualTypeArguments()) {
+ rawType = rawType.replaceParam(i, typeUsageFor(actualTypeArgument, typeSolver)).asReferenceTypeUsage();
+ i++;
+ }
+ return rawType;
} else if (type instanceof Class) {
Class c = (Class) type;
if (c.isPrimitive()) {
@@ -53,9 +55,29 @@
} else {
return new ReferenceTypeUsage(new ReflectionClassDeclaration(c, typeSolver), typeSolver);
}
- } else if (type instanceof GenericArrayType){
- GenericArrayType genericArrayType = (GenericArrayType)type;
+ } else if (type instanceof GenericArrayType) {
+ GenericArrayType genericArrayType = (GenericArrayType) type;
return new ArrayTypeUsage(typeUsageFor(genericArrayType.getGenericComponentType(), typeSolver));
+ } else if (type instanceof WildcardType) {
+ WildcardType wildcardType = (WildcardType)type;
+ if (wildcardType.getLowerBounds().length > 0 && wildcardType.getUpperBounds().length > 0) {
+ if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].getTypeName().equals("java.lang.Object")) {
+ // ok, it does not matter
+ }
+ }
+ if (wildcardType.getLowerBounds().length > 0) {
+ if (wildcardType.getLowerBounds().length > 1) {
+ throw new UnsupportedOperationException();
+ }
+ return WildcardUsage.superBound(typeUsageFor(wildcardType.getLowerBounds()[0], typeSolver));
+ }
+ if (wildcardType.getUpperBounds().length > 0) {
+ if (wildcardType.getUpperBounds().length > 1) {
+ throw new UnsupportedOperationException();
+ }
+ return WildcardUsage.extendsBound(typeUsageFor(wildcardType.getUpperBounds()[0], typeSolver));
+ }
+ return WildcardUsage.UNBOUNDED;
} else {
throw new UnsupportedOperationException(type.getClass().getCanonicalName()+" "+type);
}
diff --git a/src/test/java/me/tomassetti/symbolsolver/resolution/ContextTest.java b/src/test/java/me/tomassetti/symbolsolver/resolution/ContextTest.java
index 5bf8c64..6d2cb6a 100644
--- a/src/test/java/me/tomassetti/symbolsolver/resolution/ContextTest.java
+++ b/src/test/java/me/tomassetti/symbolsolver/resolution/ContextTest.java
@@ -251,7 +251,7 @@
JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
TypeUsage ref = javaParserFacade.getType(refToT);
- assertEquals("java.lang.String", ref.describe());
+ assertEquals("? super java.lang.String", ref.describe());
}
@Test
diff --git a/src/test/java/me/tomassetti/symbolsolver/resolution/GenericsTest.java b/src/test/java/me/tomassetti/symbolsolver/resolution/GenericsTest.java
index 91c48eb..3d76b63 100644
--- a/src/test/java/me/tomassetti/symbolsolver/resolution/GenericsTest.java
+++ b/src/test/java/me/tomassetti/symbolsolver/resolution/GenericsTest.java
@@ -393,9 +393,9 @@
assertEquals("boolean", typeUsage.describe());
}
- @Test
- public void genericCollectionWithWildcardsPrep() throws ParseException {
- CompilationUnit cu = parseSample("GenericCollection");
+ /*@Test
+ public void genericCollectionWithWildcardsAndExtensionsPrep() throws ParseException {
+ CompilationUnit cu = parseSample("GenericCollectionWithExtension");
ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
ReturnStmt returnStmt = Navigator.findReturnStmt(method);
@@ -420,6 +420,11 @@
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).asReferenceTypeUsage();
+ assertTrue(paramType.asReferenceTypeUsage().parameters().get(0).isWildcard());
+ }
MethodUsage mu = new MethodUsage(methodDeclaration, typeSolver);
int i = 0;
for (TypeParameter tp : typeDeclaration.getTypeParameters()) {
@@ -440,6 +445,23 @@
//assertTrue(methodUsage.isPresent());
+ }*/
+
+ @Test
+ public void genericCollectionWithWildcardsAndExtensions() throws ParseException {
+ 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();
+ Expression returnStmtExpr = returnStmt.getExpr();
+ JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+
+ TypeUsage typeUsage = javaParserFacade.getType(returnStmtExpr);
+
+ assertEquals(false, typeUsage.isTypeVariable());
+ assertEquals("boolean", typeUsage.describe());
}
@Test
diff --git a/src/test/resources/GenericCollectionWithExtension.java.txt b/src/test/resources/GenericCollectionWithExtension.java.txt
new file mode 100644
index 0000000..f10e70d
--- /dev/null
+++ b/src/test/resources/GenericCollectionWithExtension.java.txt
@@ -0,0 +1,15 @@
+class Node {
+}
+
+class Comment extends Node {
+}
+
+class Foo {
+
+ public Object bar() {
+ Node node;
+ java.util.List<Node> children = new java.util.LinkedList<Node>();
+ java.util.List<Comment> commentsToAttribute;
+ return children.addAll(commentsToAttribute);
+ }
+}
diff --git a/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt b/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt
index 5cc7383..4aac73a 100644
--- a/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt
+++ b/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt
@@ -1,5 +1,5 @@
[ Class com.github.javaparser.ast.internal.Utils ]
superclass: java.lang.Object
- Line 35) list == null ? Collections.<T>emptyList() : list ==> java.util.List<E>
+ Line 35) list == null ? Collections.<T>emptyList() : list ==> java.util.List<T>
Line 39) collection == null || collection.isEmpty() ==> boolean