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