package spoon.test.constructorcallnewclass; import org.junit.Before; import org.junit.Test; import spoon.Launcher; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtNewClass; import spoon.reflect.declaration.CtClass; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.AbstractFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.test.constructorcallnewclass.testclasses.Bar; import spoon.test.constructorcallnewclass.testclasses.Foo; import spoon.test.constructorcallnewclass.testclasses.Foo2; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static spoon.testing.utils.ModelUtils.build; import static spoon.testing.utils.ModelUtils.canBeBuilt; public class NewClassTest { private List<CtNewClass<?>> newClasses; @Before public void setUp() throws Exception { final Factory build = build(Foo.class); final CtClass<?> foo = (CtClass<?>) build.Type().get(Foo.class); newClasses = foo.getElements(new AbstractFilter<CtNewClass<?>>(CtNewClass.class) { @Override public boolean matches(CtNewClass<?> element) { return true; } }); } @Test public void testNewClassWithObjectClass() throws Exception { final CtNewClass<?> newClass = newClasses.get(0); assertType(Object.class, newClass); assertIsConstructor(newClass.getExecutable()); assertHasParameters(0, newClass.getArguments()); assertIsAnonymous(newClass.getAnonymousClass()); assertSuperClass(Object.class, newClass.getAnonymousClass()); } @Test public void testNewClassWithInterface() throws Exception { final CtNewClass<?> newClass = newClasses.get(1); assertType(Foo.Bar.class, newClass); assertIsConstructor(newClass.getExecutable()); assertHasParameters(0, newClass.getArguments()); assertIsAnonymous(newClass.getAnonymousClass()); assertSuperInterface(Foo.Bar.class, newClass.getAnonymousClass()); } @Test public void testNewClassWithInterfaceGeneric() throws Exception { final CtNewClass<?> newClass = newClasses.get(2); assertType(Foo.Tacos.class, newClass); assertIsConstructor(newClass.getExecutable()); assertHasParameters(0, newClass.getArguments()); assertIsAnonymous(newClass.getAnonymousClass()); assertSuperInterface(Foo.Tacos.class, newClass.getAnonymousClass()); CtTypeReference[] ctTypeReferences = newClass.getAnonymousClass().getSuperInterfaces().toArray(new CtTypeReference[0]); assertEquals("Super interface is typed by the class of the constructor", String.class, ctTypeReferences[0].getActualTypeArguments().get(0).getActualClass()); } @Test public void testNewClassInterfaceWithParameters() throws Exception { final CtNewClass<?> newClass = newClasses.get(3); assertType(Foo.BarImpl.class, newClass); assertIsConstructor(newClass.getExecutable()); assertHasParameters(1, newClass.getArguments()); assertIsAnonymous(newClass.getAnonymousClass()); assertSuperClass(Foo.BarImpl.class, newClass.getAnonymousClass()); } @Test public void testNewClassInEnumeration() throws Exception { Factory factory = null; try { factory = build(Bar.class); } catch (NullPointerException e) { fail(); } final CtClass<?> foo = (CtClass<?>) factory.Type().get(Bar.class); final CtNewClass<?> newClass = foo.getElements(new TypeFilter<CtNewClass<?>>(CtNewClass.class)).get(0); assertIsConstructor(newClass.getExecutable()); assertHasParameters(1, newClass.getArguments()); assertEquals("\">\"", newClass.getArguments().get(0).toString()); assertIsAnonymous(newClass.getAnonymousClass()); assertSuperClass(Bar.class, newClass.getAnonymousClass()); } private void assertSuperClass(Class<?> expected, CtClass<?> anonymousClass) { assertEquals("There isn't a super interface if there is a super class", 0, anonymousClass.getSuperInterfaces().size()); assertEquals("There is a super class if there isn't a super interface", expected, anonymousClass.getSuperclass().getActualClass()); } private void assertSuperInterface(Class<?> expected, CtClass<?> anonymousClass) { assertNull("There isn't super class if there is a super interface", anonymousClass.getSuperclass()); assertEquals("There is a super interface if there isn't super class", expected, anonymousClass.getSuperInterfaces().toArray(new CtTypeReference[0])[0].getActualClass()); } private void assertIsAnonymous(CtClass<?> anonymousClass) { assertTrue("Class in CtNewClass is anonymous", anonymousClass.isAnonymous()); } private void assertHasParameters(int sizeExpected, List<CtExpression<?>> arguments) { if (sizeExpected == 0) { assertEquals("New class without parameter", sizeExpected, arguments.size()); } else { assertEquals("New class with parameters", sizeExpected, arguments.size()); } } private void assertIsConstructor(CtExecutableReference<?> executable) { assertTrue("Method must be a constructor", executable.isConstructor()); } private void assertType(Class<?> typeExpected, CtNewClass<?> newClass) { assertEquals("New class is typed by the class of the constructor", typeExpected, newClass.getType().getActualClass()); } @Test public void testMoreThan9NewClass() throws Exception { final Factory build = build(Foo2.class); final CtClass<?> foo = (CtClass<?>) build.Type().get(Foo2.class); List<CtNewClass<?>> elements = foo.getElements(new AbstractFilter<CtNewClass<?>>(CtNewClass.class) { @Override public boolean matches(CtNewClass<?> element) { return true; } }); assertEquals(13, elements.size()); assertEquals(Foo2.class.getCanonicalName() + "$12", elements.get(11).getAnonymousClass().getQualifiedName()); assertEquals(Foo2.class.getCanonicalName() + "$12$1", elements.get(12).getAnonymousClass().getQualifiedName()); } @Test public void testCtNewClassInNoClasspath() throws Exception { final Launcher launcher = new Launcher(); launcher.addInputResource("./src/test/resources/new-class"); launcher.setSourceOutputDirectory("./target/new-class"); launcher.getEnvironment().setNoClasspath(true); launcher.run(); final CtClass<Object> aClass = launcher.getFactory().Class().get("IndexWriter"); final List<CtNewClass> ctNewClasses = aClass.getElements(new TypeFilter<>(CtNewClass.class)); final CtNewClass ctNewClass = ctNewClasses.get(0); final CtNewClass secondNewClass = ctNewClasses.get(1); final CtClass anonymousClass = ctNewClass.getAnonymousClass(); assertNotNull(anonymousClass); assertNotNull(anonymousClass.getSuperclass()); assertEquals("With", anonymousClass.getSuperclass().getSimpleName()); assertEquals("org.apache.lucene.store.Lock$With", anonymousClass.getSuperclass().getQualifiedName()); assertEquals("Lock", anonymousClass.getSuperclass().getDeclaringType().getSimpleName()); assertEquals("org.apache.lucene.store.Lock.With", anonymousClass.getSuperclass().toString()); assertEquals("1", anonymousClass.getSimpleName()); assertEquals("2", secondNewClass.getAnonymousClass().getSimpleName()); assertEquals(1, anonymousClass.getMethods().size()); canBeBuilt("./target/new-class", 8, true); } }