package spoon.reflect.ast; import org.junit.Assert; import org.junit.Test; import spoon.Launcher; import spoon.processing.AbstractProcessor; import spoon.reflect.code.CtConditional; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.Query; import spoon.reflect.visitor.filter.TypeFilter; import java.util.stream.Collectors; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class CloneTest { @Test public void testCloneMethodsDeclaredInAST() throws Exception { final Launcher launcher = new Launcher(); launcher.setArgs(new String[] {"--output-type", "nooutput" }); launcher.getEnvironment().setNoClasspath(true); // interfaces. launcher.addInputResource("./src/main/java/spoon/reflect/code"); launcher.addInputResource("./src/main/java/spoon/reflect/declaration"); launcher.addInputResource("./src/main/java/spoon/reflect/reference"); // implementations. launcher.addInputResource("./src/main/java/spoon/support/reflect/code"); launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration"); launcher.addInputResource("./src/main/java/spoon/support/reflect/reference"); launcher.run(); new CtScanner() { @Override public <T> void visitCtClass(CtClass<T> ctClass) { if (!ctClass.getSimpleName().startsWith("Ct")) { return; } final CtMethod<Object> clone = ctClass.getMethod("clone"); assertNotNull(ctClass.getQualifiedName() + " hasn't clone method.", clone); assertTrue(ctClass.getQualifiedName() + " hasn't Override annotation on clone method.", clone.getAnnotations().stream().map(ctAnnotation -> ctAnnotation.getActualAnnotation().annotationType()).collect(Collectors.toList()).contains(Override.class)); } @Override public <T> void visitCtInterface(CtInterface<T> intrface) { if (!intrface.getSimpleName().startsWith("Ct")) { return; } final CtMethod<Object> clone = intrface.getMethod("clone"); if (hasConcreteImpl(intrface)) { assertNotNull(intrface.getQualifiedName() + " hasn't clone method.", clone); if (!isRootDeclaration(intrface)) { assertTrue(intrface.getQualifiedName() + " hasn't Override annotation on clone method.", clone.getAnnotations().stream().map(ctAnnotation -> ctAnnotation.getActualAnnotation().annotationType()).collect(Collectors.toList()).contains(Override.class)); } } } private <T> boolean hasConcreteImpl(CtInterface<T> intrface) { return Query.getElements(intrface.getFactory(), new TypeFilter<CtClass<?>>(CtClass.class) { @Override public boolean matches(CtClass<?> element) { return super.matches(element) && element.getSuperInterfaces().contains(intrface.getReference()); } }).size() > 0; } private <T> boolean isRootDeclaration(CtInterface<T> intrface) { return "CtElement".equals(intrface.getSimpleName()); } }.scan(launcher.getModel().getRootPackage()); } @Test public void testCloneCastConditional() throws Exception { final Launcher launcher = new Launcher(); launcher.setArgs(new String[] {"--output-type", "nooutput" }); launcher.getEnvironment().setNoClasspath(true); launcher.addInputResource("./src/test/resources/spoon/test/visitor/ConditionalRes.java"); launcher.addProcessor(new AbstractProcessor<CtConditional<?>>() { @Override public void process(CtConditional<?> conditional) { CtConditional clone = conditional.clone(); Assert.assertEquals(0, conditional.getTypeCasts().size()); Assert.assertEquals(0, clone.getTypeCasts().size()); Assert.assertEquals(conditional, clone); conditional.addTypeCast(getFactory().Type().bytePrimitiveType()); Assert.assertEquals(1, conditional.getTypeCasts().size()); Assert.assertNotEquals(conditional, clone); clone = conditional.clone(); Assert.assertEquals(conditional, clone); Assert.assertEquals(1, clone.getTypeCasts().size()); } }); launcher.run(); } }