package spoon.test.constructor;
import org.junit.Before;
import org.junit.Test;
import spoon.Launcher;
import spoon.SpoonAPI;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtTypeParameter;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtIntersectionTypeReference;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.TypeFilter;
import spoon.test.constructor.testclasses.AClass;
import spoon.test.constructor.testclasses.Tacos;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static spoon.testing.utils.ModelUtils.canBeBuilt;
public class ConstructorTest {
private Factory factory;
private CtClass<?> aClass;
@Before
public void setUp() throws Exception {
SpoonAPI launcher = new Launcher();
launcher.run(new String[] {
"-i", "./src/test/java/spoon/test/constructor/testclasses/",
"-o", "./target/spooned/"
});
factory = launcher.getFactory();
aClass = factory.Class().get(Tacos.class);
}
@Test
public void testTransformationOnConstructorWithInsertBegin() throws Exception {
final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0);
ctConstructor.getBody().insertBegin(factory.Code().createCodeSnippetStatement("int i = 0"));
assertEquals(2, ctConstructor.getBody().getStatements().size());
assertEquals("super()", ctConstructor.getBody().getStatement(0).toString());
canBeBuilt("./target/spooned/spoon/test/constructor/testclasses/", 8);
}
@Test
public void testTransformationOnConstructorWithInsertBefore() throws Exception {
final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0);
try {
ctConstructor.getBody().getStatement(0).insertBefore(factory.Code().createCodeSnippetStatement("int i = 0"));
fail();
} catch (RuntimeException ignore) {
}
assertEquals(1, ctConstructor.getBody().getStatements().size());
assertEquals("super()", ctConstructor.getBody().getStatement(0).toString());
}
@Test
public void callParamConstructor() throws Exception {
CtClass<Object> aClass = factory.Class().get(AClass.class);
CtConstructor<Object> constructor = aClass.getConstructors().iterator().next();
assertEquals("{" + System.lineSeparator() +
" enclosingInstance.super();" + System.lineSeparator()
+ "}", constructor.getBody().toString());
}
@Test
public void testConstructorCallFactory() throws Exception {
CtTypeReference<ArrayList> ctTypeReference = factory.Code()
.createCtTypeReference(ArrayList.class);
CtConstructorCall<ArrayList> constructorCall = factory.Code()
.createConstructorCall(ctTypeReference);
assertEquals("new java.util.ArrayList()", constructorCall.toString());
CtConstructorCall<ArrayList> constructorCallWithParameter = factory.Code()
.createConstructorCall(ctTypeReference, constructorCall);
assertEquals("new java.util.ArrayList(new java.util.ArrayList())", constructorCallWithParameter.toString());
}
@Test
public void testTypeAnnotationOnExceptionDeclaredInConstructors() throws Exception {
final CtConstructor<?> aConstructor = aClass.getConstructor(factory.Type().OBJECT);
assertEquals(1, aConstructor.getThrownTypes().size());
Set<CtTypeReference<? extends Throwable>> thrownTypes = aConstructor.getThrownTypes();
final CtTypeReference[] thrownTypesReference = thrownTypes.toArray(new CtTypeReference[thrownTypes.size()]);
assertEquals(1, thrownTypesReference.length);
assertEquals(1, thrownTypesReference[0].getAnnotations().size());
assertEquals("java.lang.@spoon.test.constructor.testclasses.Tacos.TypeAnnotation(integer = 1)" + System.lineSeparator() + "Exception", thrownTypesReference[0].toString());
}
@Test
public void testTypeAnnotationWithConstructorsOnFormalType() throws Exception {
final CtConstructor<?> aConstructor = aClass.getConstructor(factory.Type().OBJECT);
assertEquals(1, aConstructor.getFormalCtTypeParameters().size());
// New type parameter declaration.
CtTypeParameter typeParameter = aConstructor.getFormalCtTypeParameters().get(0);
assertEquals("T", typeParameter.getSimpleName());
assertEquals(1, typeParameter.getAnnotations().size());
assertIntersectionTypeInConstructor(typeParameter.getSuperclass());
}
private void assertIntersectionTypeInConstructor(CtTypeReference<?> boundingType1) {
assertTrue(boundingType1 instanceof CtIntersectionTypeReference);
CtIntersectionTypeReference<?> boundingType = boundingType1.asCtIntersectionTypeReference();
final List<CtTypeReference<?>> bounds = boundingType.getBounds().stream().collect(Collectors.toList());
CtTypeReference<?> genericTacos = bounds.get(0);
assertEquals("Tacos", genericTacos.getSimpleName());
assertEquals(1, genericTacos.getAnnotations().size());
assertEquals(1, genericTacos.getActualTypeArguments().size());
CtTypeParameterReference wildcard = (CtTypeParameterReference) genericTacos.getActualTypeArguments().get(0);
assertEquals("?", wildcard.getSimpleName());
assertEquals(1, wildcard.getAnnotations().size());
assertEquals("C", wildcard.getBoundingType().getSimpleName());
assertEquals(1, wildcard.getBoundingType().getAnnotations().size());
assertEquals("Serializable", bounds.get(1).getSimpleName());
assertEquals(1, bounds.get(1).getAnnotations().size());
}
}