package spoon.test.casts; import org.junit.Test; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtVariableRead; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.Query; import spoon.reflect.visitor.filter.NameFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.testing.utils.ModelUtils; import static org.junit.Assert.assertEquals; import static spoon.testing.utils.ModelUtils.build; import static spoon.testing.utils.ModelUtils.buildClass; public class CastTest { Factory factory = ModelUtils.createFactory(); @Test public void testCast1() { CtClass<?> clazz = factory .Code() .createCodeSnippetStatement( "" + "class X {" + "public void foo() {" + " String x=(String) new Object();" + "}" + "};").compile(); CtMethod<?> foo = (CtMethod<?>) clazz.getMethods().toArray()[0]; assertEquals( "java.lang.String x = ((java.lang.String) (new java.lang.Object()))", foo.getBody().getStatements().get(0).toString()); } @Test public void testCast2() { CtClass<?> clazz = factory .Code() .createCodeSnippetStatement( "" + "class X {" + "public void foo() {" + " Class<String> x=(Class<String>) new Object();" + "}" + "};").compile(); CtMethod<?> foo = (CtMethod<?>) clazz.getMethods().toArray()[0]; assertEquals( "java.lang.Class<java.lang.String> x = ((java.lang.Class<java.lang.String>) (new java.lang.Object()))", foo.getBody().getStatements().get(0).toString()); } @Test public void testCast3() { CtClass<?> clazz = factory .Code() .createCodeSnippetStatement( "" + "class X<A> {" + "void addConsumedAnnotationType(Class<? extends A> annotationType) {}\n" + "public void foo() {" + " Class<?> x = null;" + " addConsumedAnnotationType((Class<A>) x);" + "}" + "};").compile(); CtMethod<?> foo = clazz.getElements(new NameFilter<CtMethod<?>>("foo")) .get(0); CtVariableRead<?> a = (CtVariableRead<?>) clazz.getElements( new TypeFilter<>(CtVariableRead.class)).get(0); assertEquals(1, a.getTypeCasts().size()); assertEquals("addConsumedAnnotationType(((java.lang.Class<A>) (x)))", foo.getBody().getStatements().get(1).toString()); } @Test public void testCase4() throws Exception { // contract: If the invocation is to a method where the returned type is a generic type, // getType returns the actual type bound to this particular invocation. CtType<?> type = build("spoon.test.casts", "Castings"); final CtMethod<?> getValueMethod = type.getMethodsByName("getValue").get(0); final CtInvocation<?> getValueInvocation = Query.getElements(type, new TypeFilter<CtInvocation<?>>(CtInvocation.class) { @Override public boolean matches(CtInvocation element) { return "getValue".equals(element.getExecutable().getSimpleName()) && super.matches(element); } }).get(0); assertEquals("T", getValueMethod.getType().getSimpleName()); assertEquals("T", getValueMethod.getParameters().get(0).getType().getActualTypeArguments().get(0).toString()); assertEquals(type.getFactory().Class().INTEGER, getValueInvocation.getType()); } @Test public void testTypeAnnotationOnCast() throws Exception { final CtType<Castings> aCastings = buildClass(Castings.class); final CtLocalVariable local = aCastings.getMethod("bar").getElements(new TypeFilter<>(CtLocalVariable.class)).get(0); assertEquals(1, ((CtTypeReference) local.getDefaultExpression().getTypeCasts().get(0)).getAnnotations().size()); assertEquals("((java.lang.@spoon.test.casts.Castings.TypeAnnotation(integer = 1)" + System.lineSeparator() + "String) (\"\"))", local.getDefaultExpression().toString()); } }