From ce2856d78599abb494a92e10995931076fc01a92 Mon Sep 17 00:00:00 2001 From: Pavel Vojtechovsky Date: Thu, 2 Feb 2017 09:22:14 +0100 Subject: [PATCH] fix:bug in isSubtypeOf (broken contract X.isSubtypeOf(X)==true) (#1157) * test X.isSubtypeOf(X)==true * Change implementation of isSubtypeOf for different implementations to use method defined in CtTypeReferenceImpl. * Add one more test to check isSubtypeOf for TypeParameters. * fix checkstyle * comment test of not yet supported isSubTypeOf TypedParameter * added comment typeX.isSubtypeOf(typeX) is true --- .../declaration/CtTypeInformation.java | 1 + .../declaration/CtAnnotationTypeImpl.java | 2 +- .../reflect/declaration/CtClassImpl.java | 10 +---- .../reflect/declaration/CtEnumImpl.java | 7 +--- .../reflect/declaration/CtInterfaceImpl.java | 7 +--- .../declaration/CtTypeParameterImpl.java | 2 +- .../CtTypeParameterReferenceImpl.java | 5 --- .../java/spoon/test/ctType/CtTypeTest.java | 38 ++++++++++++++++++- .../java/spoon/test/ctType/testclasses/X.java | 6 +++ 9 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/main/java/spoon/reflect/declaration/CtTypeInformation.java b/src/main/java/spoon/reflect/declaration/CtTypeInformation.java index e32c9cea4e7..9e82f234d20 100644 --- a/src/main/java/spoon/reflect/declaration/CtTypeInformation.java +++ b/src/main/java/spoon/reflect/declaration/CtTypeInformation.java @@ -98,6 +98,7 @@ public interface CtTypeInformation { /** * Returns true if the referenced type is a sub-type of the given type. + * Returns true is type is self, it means: typeX.isSubtypeOf(typeX) is true too */ boolean isSubtypeOf(CtTypeReference type); diff --git a/src/main/java/spoon/support/reflect/declaration/CtAnnotationTypeImpl.java b/src/main/java/spoon/support/reflect/declaration/CtAnnotationTypeImpl.java index fe4612f152c..dd896ea69d2 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtAnnotationTypeImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtAnnotationTypeImpl.java @@ -66,7 +66,7 @@ public > C setSuperInterfaces(Set> interf @Override public boolean isSubtypeOf(CtTypeReference type) { - return false; + return getReference().isSubtypeOf(type); } @Override diff --git a/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java b/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java index 056344edb97..447150f039f 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java @@ -176,15 +176,7 @@ public boolean isAnonymous() { @Override public boolean isSubtypeOf(CtTypeReference type) { - if ((getSuperclass() != null) && getSuperclass().isSubtypeOf(type)) { - return true; - } - for (CtTypeReference ref : getSuperInterfaces()) { - if (ref.isSubtypeOf(type)) { - return true; - } - } - return false; + return getReference().isSubtypeOf(type); } @Override diff --git a/src/main/java/spoon/support/reflect/declaration/CtEnumImpl.java b/src/main/java/spoon/support/reflect/declaration/CtEnumImpl.java index 15dba24393d..0e2f751e933 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtEnumImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtEnumImpl.java @@ -56,12 +56,7 @@ public Set> getAllMethods() { @Override public boolean isSubtypeOf(CtTypeReference type) { - for (CtTypeReference ref : getSuperInterfaces()) { - if (ref.isSubtypeOf(type)) { - return true; - } - } - return getSuperclass().isSubtypeOf(type); + return getReference().isSubtypeOf(type); } @Override diff --git a/src/main/java/spoon/support/reflect/declaration/CtInterfaceImpl.java b/src/main/java/spoon/support/reflect/declaration/CtInterfaceImpl.java index 2947f7a0d28..34c28e919cc 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtInterfaceImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtInterfaceImpl.java @@ -39,12 +39,7 @@ public void accept(CtVisitor visitor) { @Override public boolean isSubtypeOf(CtTypeReference type) { - for (CtTypeReference ref : getSuperInterfaces()) { - if (ref.isSubtypeOf(type)) { - return true; - } - } - return false; + return getReference().isSubtypeOf(type); } @Override diff --git a/src/main/java/spoon/support/reflect/declaration/CtTypeParameterImpl.java b/src/main/java/spoon/support/reflect/declaration/CtTypeParameterImpl.java index f70340e6bc9..f20478a803b 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtTypeParameterImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtTypeParameterImpl.java @@ -234,7 +234,7 @@ public List> getDeclaredFields() { @Override public boolean isSubtypeOf(CtTypeReference type) { - return false; + return getReference().isSubtypeOf(type); } @Override diff --git a/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java b/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java index be36704b551..50e9b7de466 100644 --- a/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java +++ b/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java @@ -81,11 +81,6 @@ public boolean isGenerics() { return true; } - @Override - public boolean isSubtypeOf(CtTypeReference type) { - return false; - } - @Override public boolean isPrimitive() { return false; diff --git a/src/test/java/spoon/test/ctType/CtTypeTest.java b/src/test/java/spoon/test/ctType/CtTypeTest.java index 73d44b32277..0ff2aa05608 100644 --- a/src/test/java/spoon/test/ctType/CtTypeTest.java +++ b/src/test/java/spoon/test/ctType/CtTypeTest.java @@ -6,9 +6,14 @@ import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.CtTypeMember; +import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.factory.Factory; +import spoon.reflect.reference.CtTypeReference; import spoon.test.ctType.testclasses.X; +import java.util.List; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static spoon.testing.utils.ModelUtils.buildClass; @@ -69,8 +74,37 @@ public void testHasMethodInDefaultMethod() throws Exception { @Test public void testIsSubTypeOf() throws Exception { CtType xCtType = buildClass(X.class); + CtType yCtType = xCtType.getFactory().Type().get("spoon.test.ctType.testclasses.Y"); + + assertFalse(xCtType.isSubtypeOf(yCtType.getReference())); + assertTrue(yCtType.isSubtypeOf(xCtType.getReference())); + //contract: x isSubtypeOf x + //using CtTypeReference implementation + assertTrue(xCtType.getReference().isSubtypeOf(xCtType.getReference())); + //using CtType implementation + assertTrue(xCtType.isSubtypeOf(xCtType.getReference())); + } + + @Test + public void testIsSubTypeOfonTypeParameters() throws Exception { + CtType xCtType = buildClass(X.class); + + CtType oCtType = xCtType.getFactory().Type().get("spoon.test.ctType.testclasses.O"); + + List typeParameters = oCtType.getFormalCtTypeParameters(); + assertTrue(typeParameters.size() == 1); + + CtType aCtType = typeParameters.get(0); + + List> methods = oCtType.getMethodsByName("foo"); + + assertTrue(methods.size() == 1); + + CtMethod fooMethod = methods.get(0); + CtType bCtType = fooMethod.getType().getDeclaration(); - assertFalse(xCtType.isSubtypeOf(xCtType.getFactory().Type().createReference("spoon.test.ctType.testclasses.Y"))); - assertTrue(xCtType.getFactory().Type().get("spoon.test.ctType.testclasses.Y").isSubtypeOf(xCtType.getReference())); + //The TypeParameters are not supported yet +// assertTrue(bCtType.isSubtypeOf(xCtType.getReference())); +// assertTrue(bCtType.isSubtypeOf(aCtType.getReference())); } } diff --git a/src/test/java/spoon/test/ctType/testclasses/X.java b/src/test/java/spoon/test/ctType/testclasses/X.java index b06236046ea..60266fb5297 100644 --- a/src/test/java/spoon/test/ctType/testclasses/X.java +++ b/src/test/java/spoon/test/ctType/testclasses/X.java @@ -17,3 +17,9 @@ interface Z { abstract class W implements Z { } +class O { + B foo() { + return null; + } +} +