improve isAssignableBy when Wildcards are involved
diff --git a/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/model/typesystem/ReferenceTypeUsageImpl.java b/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/model/typesystem/ReferenceTypeUsageImpl.java
index ffcdc2b..cf9e091 100644
--- a/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/model/typesystem/ReferenceTypeUsageImpl.java
+++ b/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/model/typesystem/ReferenceTypeUsageImpl.java
@@ -70,6 +70,14 @@
         } else if (other.isTypeVariable()) {
             // TODO look bounds...
             return true;
+        } else if (other.isWildcard()) {
+            if (this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+                return true;
+            } else if (other.asWildcard().isExtends()) {
+                return isAssignableBy(other.asWildcard().getBoundedType());
+            } else {
+                return false;
+            }
         } else {
             return false;
         }
diff --git a/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java b/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
index 05f92f9..ac1fcd3 100644
--- a/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
+++ b/java-symbol-solver-core/src/main/java/me/tomassetti/symbolsolver/resolution/javaparser/contexts/MethodCallExprContext.java
@@ -7,9 +7,7 @@
 import me.tomassetti.symbolsolver.model.declarations.ValueDeclaration;
 import me.tomassetti.symbolsolver.model.invokations.MethodUsage;
 import me.tomassetti.symbolsolver.model.resolution.*;
-import me.tomassetti.symbolsolver.model.typesystem.ReferenceTypeUsageImpl;
-import me.tomassetti.symbolsolver.model.typesystem.TypeParameterUsage;
-import me.tomassetti.symbolsolver.model.typesystem.TypeUsage;
+import me.tomassetti.symbolsolver.model.typesystem.*;
 import me.tomassetti.symbolsolver.resolution.javaparser.JavaParserFacade;
 import me.tomassetti.symbolsolver.resolution.javaparser.UnsolvedSymbolException;
 import me.tomassetti.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
@@ -32,7 +30,7 @@
         return typeOfScope.asReferenceTypeUsage().getGenericParameterByName(name);
     }
 
-    private Optional<MethodUsage> solveMethodAsUsage(ReferenceTypeUsageImpl refType, String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver, Context invokationContext) {
+    private Optional<MethodUsage> solveMethodAsUsage(ReferenceTypeUsage refType, String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver, Context invokationContext) {
         Optional<MethodUsage> ref = refType.getTypeDeclaration().solveMethodAsUsage(name, parameterTypes, typeSolver, invokationContext, refType.parameters());
         if (ref.isPresent()) {
             MethodUsage methodUsage = ref.get();
@@ -66,12 +64,21 @@
     }
 
     private Optional<MethodUsage> solveMethodAsUsage(TypeUsage typeUsage, String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver, Context invokationContext) {
-        if (typeUsage instanceof ReferenceTypeUsageImpl) {
-            return solveMethodAsUsage((ReferenceTypeUsageImpl) typeUsage, name, parameterTypes, typeSolver, invokationContext);
+        if (typeUsage instanceof ReferenceTypeUsage) {
+            return solveMethodAsUsage((ReferenceTypeUsage) typeUsage, name, parameterTypes, typeSolver, invokationContext);
         } else if (typeUsage instanceof TypeParameterUsage) {
             return solveMethodAsUsage((TypeParameterUsage) typeUsage, name, parameterTypes, typeSolver, invokationContext);
+        } else if (typeUsage instanceof WildcardUsage) {
+            WildcardUsage wildcardUsage = (WildcardUsage)typeUsage;
+            if (wildcardUsage.isSuper()) {
+                return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, parameterTypes, typeSolver, invokationContext);
+            } else if (wildcardUsage.isExtends()) {
+                throw new UnsupportedOperationException("extends wildcard");
+            } else {
+                throw new UnsupportedOperationException("unbounded wildcard");
+            }
         } else {
-            throw new UnsupportedOperationException();
+            throw new UnsupportedOperationException("type usage: " + typeUsage.getClass().getCanonicalName());
         }
     }
 
diff --git a/java-symbol-solver-core/src/test/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsageTest.java b/java-symbol-solver-core/src/test/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsageTest.java
index a1bbee1..ec5c6bb 100644
--- a/java-symbol-solver-core/src/test/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsageTest.java
+++ b/java-symbol-solver-core/src/test/java/me/tomassetti/symbolsolver/model/typesystem/WildcardUsageTest.java
@@ -8,6 +8,7 @@
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.List;
 
 import static org.junit.Assert.*;
 
@@ -20,6 +21,7 @@
     private TypeSolver typeSolver;
     private ReferenceTypeUsageImpl foo;
     private ReferenceTypeUsageImpl bar;
+    private ReferenceTypeUsageImpl object;
     private ReferenceTypeUsageImpl string;
     private WildcardUsage unbounded = WildcardUsage.UNBOUNDED;
     private WildcardUsage superFoo;
@@ -37,6 +39,7 @@
         typeSolver = new JreTypeSolver();
         foo = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(Foo.class, typeSolver), typeSolver);
         bar = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(Bar.class, typeSolver), typeSolver);
+        object = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         string = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
         superFoo = WildcardUsage.superBound(foo);
         superBar = WildcardUsage.superBound(bar);
@@ -169,25 +172,18 @@
         assertTrue(extendsA == extendsA.replaceParam("B", string));
     }
 
-    /*@Test
+    @Test
     public void testIsAssignableBySimple() {
-        assertEquals(true, object.isAssignableBy(string));
-        assertEquals(false, string.isAssignableBy(object));
-        assertEquals(false, listOfStrings.isAssignableBy(listOfA));
-        assertEquals(false, listOfA.isAssignableBy(listOfStrings));
-
-        assertEquals(false, object.isAssignableBy(VoidTypeUsage.INSTANCE));
-        assertEquals(false, string.isAssignableBy(VoidTypeUsage.INSTANCE));
-        assertEquals(false, listOfStrings.isAssignableBy(VoidTypeUsage.INSTANCE));
-        assertEquals(false, listOfA.isAssignableBy(VoidTypeUsage.INSTANCE));
-
-        assertEquals(true, object.isAssignableBy(NullTypeUsage.INSTANCE));
-        assertEquals(true, string.isAssignableBy(NullTypeUsage.INSTANCE));
-        assertEquals(true, listOfStrings.isAssignableBy(NullTypeUsage.INSTANCE));
-        assertEquals(true, listOfA.isAssignableBy(NullTypeUsage.INSTANCE));
+        assertEquals(false, unbounded.isAssignableBy(object));
+        assertEquals(true, object.isAssignableBy(unbounded));
+        assertEquals(false, string.isAssignableBy(unbounded));
+        assertEquals(true, superFoo.isAssignableBy(foo));
+        assertEquals(false, foo.isAssignableBy(superFoo));
+        assertEquals(false, extendsFoo.isAssignableBy(foo));
+        assertEquals(true, foo.isAssignableBy(extendsFoo));
     }
 
-    @Test
+    /*@Test
     public void testIsAssignableByGenerics() {
         assertEquals(false, listOfStrings.isAssignableBy(listOfWildcardExtendsString));
         assertEquals(false, listOfStrings.isAssignableBy(listOfWildcardExtendsString));
diff --git a/java-symbol-solver-examples/pom.xml b/java-symbol-solver-examples/pom.xml
index b2af5be..f0ff30b 100644
--- a/java-symbol-solver-examples/pom.xml
+++ b/java-symbol-solver-examples/pom.xml
@@ -56,7 +56,12 @@
           <groupId>com.google.guava</groupId>
           <artifactId>guava</artifactId>
           <version>18.0</version>
-      </dependency>
+     </dependency>
+     <dependency>
+          <groupId>me.tomassetti</groupId>
+          <artifactId>java-symbol-solver-core</artifactId>
+          <version>0.1-SNAPSHOT</version>
+     </dependency>
   </dependencies>
   <build>
     <plugins>
diff --git a/java-symbol-solver-examples/src/main/java/me/tomassetti/examples/PrintExpressionType.java b/java-symbol-solver-examples/src/main/java/me/tomassetti/examples/PrintExpressionType.java
new file mode 100644
index 0000000..f68c7a6
--- /dev/null
+++ b/java-symbol-solver-examples/src/main/java/me/tomassetti/examples/PrintExpressionType.java
@@ -0,0 +1,4 @@
+package me.tomassetti.examples;
+
+public class PrintExpressionType {
+}
diff --git a/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Address.java b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Address.java
new file mode 100644
index 0000000..2037d14
--- /dev/null
+++ b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Address.java
@@ -0,0 +1,42 @@
+package someproject.me.tomassetti;
+
+public class Address {
+    private String street;
+    private int number;
+    private String city;
+    private int zipCode;
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public int getNumber() {
+        return number;
+    }
+
+    public void setNumber(int number) {
+        this.number = number;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public int getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(int zipCode) {
+        this.zipCode = zipCode;
+    }
+
+
+}
diff --git a/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Agenda.java b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Agenda.java
new file mode 100644
index 0000000..4c8664c
--- /dev/null
+++ b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Agenda.java
@@ -0,0 +1,22 @@
+package someproject.me.tomassetti;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class Agenda {
+
+    private List<Person> persons = new ArrayList<>();
+
+    public void addPerson(Person person) {
+        persons.add(person);
+    }
+
+    public List<Address> findAddressesOfPersons(String personName) {
+        return persons.stream().
+                filter(p -> p.getName().equals(personName)).
+                map(p -> p.getAddress()).
+                collect(Collectors.toList());
+    }
+
+}
diff --git a/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Person.java b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Person.java
new file mode 100644
index 0000000..98b014d
--- /dev/null
+++ b/java-symbol-solver-examples/src/main/resources/someproject/me/tomassetti/Person.java
@@ -0,0 +1,24 @@
+package someproject.me.tomassetti;
+
+public class Person {
+
+    private String name;
+    private Address address;
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+
+    public String getName() {
+        return name;
+
+    }
+
+    public Address getAddress() {
+        return address;
+    }
+}
\ No newline at end of file