package spoon.test.ctType; import org.junit.Test; import spoon.Launcher; import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtComment; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtVariableAccess; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtNamedElement; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.NameFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.test.ctType.testclasses.X; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static spoon.testing.utils.ModelUtils.buildClass; import static spoon.testing.utils.ModelUtils.createFactory; public class CtTypeTest { @Test public void testHasMethodInDirectMethod() { CtClass<?> clazz = createFactory().Code().createCodeSnippetStatement( "class X { public void foo() {} }").compile(); assertTrue(clazz.hasMethod(clazz.getMethods().iterator().next())); } @Test public void testHasMethodNotHasMethod() { Factory factory = createFactory(); CtClass<?> clazz = factory.Code().createCodeSnippetStatement( "class X { public void foo() {} }").compile(); CtClass<?> clazz2 = factory.Code().createCodeSnippetStatement( "class Y { public void foo2() {} }").compile(); assertFalse(clazz.hasMethod(clazz2.getMethods().iterator().next())); } @Test public void testHasMethodOnNull() { CtClass<?> clazz = createFactory().Code().createCodeSnippetStatement( "class X { public void foo() {} }").compile(); assertFalse(clazz.hasMethod(null)); } @Test public void testHasMethodInSuperClass() throws Exception { final Launcher launcher = new Launcher(); launcher.addInputResource("./src/test/java/spoon/test/ctType/testclasses/X.java"); launcher.run(); final CtClass<?> xClass = launcher.getFactory().Class().get("spoon.test.ctType.testclasses.X"); final CtClass<?> yClass = launcher.getFactory().Class().get("spoon.test.ctType.testclasses.Y"); final CtMethod<?> superMethod = xClass.getMethods().iterator().next(); assertTrue(yClass.hasMethod(superMethod)); } @Test public void testHasMethodInDefaultMethod() throws Exception { final Launcher launcher = new Launcher(); launcher.addInputResource("./src/test/java/spoon/test/ctType/testclasses/X.java"); launcher.getEnvironment().setComplianceLevel(8); launcher.run(); final CtClass<?> x = launcher.getFactory().Class().get("spoon.test.ctType.testclasses.W"); final CtInterface<?> z = launcher.getFactory().Interface().get("spoon.test.ctType.testclasses.Z"); final CtMethod<?> superMethod = z.getMethods().iterator().next(); assertTrue(x.hasMethod(superMethod)); } @Test public void testIsSubTypeOf() throws Exception { CtType<X> 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<X> xCtType = buildClass(X.class); Factory factory = xCtType.getFactory(); CtType<?> oCtType = factory.Type().get("spoon.test.ctType.testclasses.O"); CtType<?> pCtType = factory.Type().get("spoon.test.ctType.testclasses.P"); CtTypeReference<?> objectCtTypeRef = factory.Type().OBJECT; List<CtTypeParameter> oTypeParameters = oCtType.getFormalCtTypeParameters(); assertTrue(oTypeParameters.size() == 1); List<CtTypeParameter> pTypeParameters = pCtType.getFormalCtTypeParameters(); assertTrue(pTypeParameters.size() == 2); CtType<?> O_A_CtType = oTypeParameters.get(0); CtType<?> P_D_CtType = pTypeParameters.get(0); CtType<?> P_F_CtType = pTypeParameters.get(1); CtMethod<?> O_FooMethod = oCtType.filterChildren(new NameFilter<>("foo")).first(); CtMethod<?> P_FooMethod = pCtType.filterChildren(new NameFilter<>("foo")).first(); CtType<?> O_B_CtType = O_FooMethod.getType().getDeclaration(); CtType<?> P_E_CtType = P_FooMethod.getType().getDeclaration(); assertTrue(O_B_CtType.isSubtypeOf(xCtType.getReference())); assertTrue(O_B_CtType.isSubtypeOf(O_A_CtType.getReference())); assertTrue(P_E_CtType.isSubtypeOf(xCtType.getReference())); assertTrue(P_E_CtType.isSubtypeOf(P_D_CtType.getReference())); assertTrue(P_E_CtType.isSubtypeOf(O_A_CtType.getReference())); assertTrue(P_D_CtType.isSubtypeOf(O_A_CtType.getReference())); assertTrue(P_E_CtType.isSubtypeOf(O_B_CtType.getReference())); assertTrue(P_E_CtType.isSubtypeOf(objectCtTypeRef)); assertTrue(P_F_CtType.isSubtypeOf(objectCtTypeRef)); } @Test public void testIsSubTypeOfonTypeReferences() throws Exception { final Launcher launcher = new Launcher(); launcher.setArgs(new String[]{"-c"}); launcher.addInputResource("./src/test/java/spoon/test/ctType/testclasses/SubtypeModel.java"); launcher.buildModel(); Factory factory = launcher.getFactory(); CtType<?> oCtType = factory.Class().get("spoon.test.ctType.testclasses.SubtypeModel"); CtMethod<?> O_FooMethod = oCtType.filterChildren(new NameFilter<>("foo")).first(); Map<String, CtTypeReference<?>> nameToTypeRef = new HashMap<>(); O_FooMethod.filterChildren(new TypeFilter<>(CtLocalVariable.class)).forEach((CtLocalVariable var)->{ nameToTypeRef.put(var.getSimpleName(), var.getType()); }); int[] count = new int[1]; O_FooMethod.filterChildren(new TypeFilter<>(CtAssignment.class)).forEach((CtAssignment ass)->{ for (CtComment comment : ass.getComments()) { checkIsNotSubtype(comment, nameToTypeRef); count[0]++; }; count[0]++; checkIsSubtype(((CtVariableAccess) ass.getAssigned()).getVariable().getType(), ((CtVariableAccess) ass.getAssignment()).getVariable().getType(), nameToTypeRef); }); assertTrue(count[0]>(9*8)); } private void checkIsSubtype(CtTypeReference superType, CtTypeReference subType, Map<String, CtTypeReference<?>> nameToTypeRef) { String msg = getTypeName(subType)+" isSubTypeOf "+getTypeName(superType); assertTrue(msg, subType.isSubtypeOf(superType)); } private static final Pattern assignment = Pattern.compile("\\s*(\\w+)\\s*=\\s*(\\w+);"); private void checkIsNotSubtype(CtComment comment, Map<String, CtTypeReference<?>> nameToTypeRef) { Matcher m = assignment.matcher(comment.getContent()); assertTrue(m.matches()); CtTypeReference<?> superType = nameToTypeRef.get(m.group(1)); CtTypeReference<?> subType = nameToTypeRef.get(m.group(2)); String msg = getTypeName(subType)+" is NOT SubTypeOf "+getTypeName(superType); assertFalse(msg, subType.isSubtypeOf(superType)); } private String getTypeName(CtTypeReference<?> ref) { String name; CtReference r= ref.getParent(CtReference.class); if(r!=null) { name = r.getSimpleName(); } else { name = ref.getParent(CtNamedElement.class).getSimpleName(); } return ref.toString()+" "+name; } }