package spoon.test.ctClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static spoon.testing.utils.ModelUtils.build;
import static spoon.testing.utils.ModelUtils.buildClass;
import static spoon.testing.utils.ModelUtils.canBeBuilt;
import java.util.Set;
import org.junit.Test;
import spoon.Launcher;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtArrayTypeReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.test.ctClass.testclasses.Foo;
import spoon.test.ctClass.testclasses.Pozole;
public class CtClassTest {
@Test
public void getConstructor() throws Exception {
final Factory build = build(Foo.class);
final CtClass<?> foo = (CtClass<?>) build.Type().get(Foo.class);
assertEquals(3, foo.getConstructors().size());
CtTypeReference<Object> typeString = build.Code().createCtTypeReference(String.class);
CtConstructor<?> constructor = foo.getConstructor(typeString);
assertEquals(typeString, constructor.getParameters().get(0).getType());
CtArrayTypeReference<Object> typeStringArray = build.Core().createArrayTypeReference();
typeStringArray.setComponentType(typeString);
constructor = foo.getConstructor(typeStringArray);
assertEquals(typeStringArray, constructor.getParameters().get(0).getType());
CtArrayTypeReference<Object> typeStringArrayArray = build.Core().createArrayTypeReference();
typeStringArrayArray.setComponentType(typeStringArray);
constructor = foo.getConstructor(typeStringArrayArray);
assertEquals(typeStringArrayArray, constructor.getParameters().get(0).getType());
}
@Test
public void testParentOfTheEnclosingClassOfStaticClass() throws Exception {
// contract: When we have a static class which extends a superclass in the classpath,
// the enclosing class don't have a superclass. This is probably a bug in JDT but good
// luck to report a bug about noclasspath in their bugtracker. :)
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/noclasspath/InvariantChecker.java");
launcher.addInputResource("./src/test/resources/noclasspath/FileIO.java");
launcher.addInputResource("./src/test/resources/noclasspath/Daikon.java");
launcher.setSourceOutputDirectory("./target/class");
launcher.getEnvironment().setNoClasspath(true);
launcher.run();
final CtClass<Object> aClass = launcher.getFactory().Class().get("daikon.tools.InvariantChecker");
final CtType<?> staticClass = aClass.getNestedType("InvariantCheckProcessor");
assertNotNull(staticClass);
assertEquals("InvariantCheckProcessor", staticClass.getSimpleName());
assertNotNull(staticClass.getSuperclass());
assertEquals("daikon.FileIO$Processor", staticClass.getSuperclass().getQualifiedName());
assertNull(aClass.getSuperclass());
canBeBuilt("./target/class", 8, true);
}
@Test
public void testNoClasspathWithSuperClassOfAClassInAnInterface() throws Exception {
// contract: When we specify a superclass which is declared in an interface and
// where the visibility is okay, we must use it.
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/noclasspath/draw2d");
launcher.setSourceOutputDirectory("./target/draw2d");
launcher.getEnvironment().setNoClasspath(true);
launcher.run();
final CtClass<Object> aClass = launcher.getFactory().Class().get("org.eclipse.draw2d.parts.ScrollableThumbnail");
final CtType<?> innerClass = aClass.getNestedType("ClickScrollerAndDragTransferrer");
assertEquals("org.eclipse.draw2d.MouseMotionListener$Stub", innerClass.getSuperclass().getQualifiedName());
canBeBuilt("./target/draw2d", 8, true);
}
@Test
public void testAllTypeReferencesToALocalTypeShouldNotStartWithNumber() throws Exception {
// contract: When we have a local type, we should never start with its number. But this
// number isn't rewrite only in the class declaration but in all type references and in
// the constructor.
final CtType<Pozole> aPozole = buildClass(Pozole.class);
final CtClass<?> cook = aPozole.getNestedType("1Cook");
assertEquals("1Cook", cook.getSimpleName());
assertEquals("spoon.test.ctClass.testclasses.Pozole$1Cook", cook.getQualifiedName());
final Set<? extends CtConstructor<?>> constructors = cook.getConstructors();
final String expectedConstructor = "public Cook() {" + System.lineSeparator() + "}";
assertEquals(expectedConstructor, constructors.toArray(new CtConstructor[constructors.size()])[0].toString());
assertEquals("final java.lang.Class<Cook> cookClass = Cook.class", cook.getMethod("m").getBody().getStatement(0).toString());
Factory factory = aPozole.getFactory();
aPozole.removeModifier(ModifierKind.PUBLIC);
factory.Code().createCodeSnippetStatement(aPozole.toString()).compile();
CtClass internalClass = factory.Core().createClass();
internalClass.setSimpleName("Foo");
cook.getParent(CtBlock.class).addStatement(internalClass);
assertEquals("Foo", internalClass.getSimpleName());
assertEquals("spoon.test.ctClass.testclasses.Pozole$Foo", internalClass.getQualifiedName());
internalClass.addConstructor(factory.Core().createConstructor());
CtConstructor cons = (CtConstructor) internalClass.getConstructors().toArray(new CtConstructor[0])[0];
cons.setBody(factory.Core().createBlock());
CtConstructorCall call = cook.getFactory().Core().createConstructorCall();
call.setExecutable(cons.getReference());
assertEquals(internalClass, internalClass.getReference().getDeclaration());
assertEquals("new Foo()", call.toString());
internalClass.insertAfter(call);
factory.getEnvironment().setAutoImports(true);
factory.Code().createCodeSnippetStatement(aPozole.toString()).compile();
factory.getEnvironment().setAutoImports(false);
factory.Code().createCodeSnippetStatement(aPozole.toString()).compile();
}
}