package spoon.test.reference; import org.junit.Test; import spoon.Launcher; import spoon.reflect.code.CtInvocation; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.visitor.Query; import spoon.reflect.visitor.filter.ReferenceTypeFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.test.reference.testclasses.Bar; import spoon.test.reference.testclasses.Burritos; import spoon.test.reference.testclasses.Kuu; import spoon.test.reference.testclasses.SuperFoo; import java.util.List; import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; public class ExecutableReferenceTest { @Test public void testCallMethodOfClassNotPresent() throws Exception { final Launcher launcher = new Launcher(); launcher.run(new String[] { "-i", "./src/test/resources/executable-reference", "--output-type", "nooutput", "--noclasspath" }); final List<CtExecutableReference<?>> references = Query.getReferences(launcher.getFactory(), new ReferenceTypeFilter<CtExecutableReference<?>>(CtExecutableReference.class) { @Override public boolean matches(CtExecutableReference<?> reference) { return !reference.isConstructor() && super.matches(reference); } }); final List<CtInvocation<?>> invocations = Query.getElements(launcher.getFactory(), new TypeFilter<CtInvocation<?>>(CtInvocation.class) { @Override public boolean matches(CtInvocation<?> element) { return !element.getExecutable().isConstructor() && super.matches(element); } }); assertEquals(4, references.size()); assertEquals(4, invocations.size()); // Executable reference with 0 parameter. final CtExecutableReference<?> executableZeroParameter = references.get(0); assertNotNull(executableZeroParameter.getDeclaringType()); assertNull(executableZeroParameter.getType()); assertEquals(0, executableZeroParameter.getParameters().size()); assertEquals("Bar#m()", executableZeroParameter.toString()); assertEquals("new Bar().m()", invocations.get(0).toString()); // Executable reference with 1 parameter and return type. final CtExecutableReference<?> executableOneParameter = references.get(1); assertNotNull(executableOneParameter.getDeclaringType()); assertNotNull(executableOneParameter.getType()); assertEquals(1, executableOneParameter.getParameters().size()); assertNotEquals(executableZeroParameter, executableOneParameter); assertEquals("Bar#m(int)", executableOneParameter.toString()); assertEquals("bar.m(1)", invocations.get(1).toString()); // Executable reference with 2 parameters. final CtExecutableReference<?> executableTwoParameters = references.get(2); assertNotNull(executableTwoParameters.getDeclaringType()); assertNull(executableTwoParameters.getType()); assertEquals(2, executableTwoParameters.getParameters().size()); assertNotEquals(executableTwoParameters, executableZeroParameter); assertNotEquals(executableTwoParameters, executableOneParameter); assertEquals("Bar#m(int, java.lang.String)", executableTwoParameters.toString()); assertEquals("new Bar().m(1, \"5\")", invocations.get(2).toString()); // Static Executable reference. final CtExecutableReference<?> staticExecutable = references.get(3); assertNotNull(staticExecutable.getDeclaringType()); assertNull(staticExecutable.getType()); assertEquals(1, staticExecutable.getParameters().size()); assertNotEquals(staticExecutable, executableZeroParameter); assertNotEquals(staticExecutable, executableOneParameter); assertEquals("Bar#m(java.lang.String)", staticExecutable.toString()); assertEquals("Bar.m(\"42\")", invocations.get(3).toString()); } @Test public void testSuperClassInGetAllExecutables() throws Exception { final Launcher launcher = new Launcher(); launcher.addInputResource("./src/test/java/spoon/test/reference/testclasses/"); launcher.setSourceOutputDirectory("./target/spoon-test"); launcher.run(); final CtClass<Burritos> aBurritos = launcher.getFactory().Class().get(Burritos.class); final CtMethod<?> aMethod = aBurritos.getMethodsByName("m").get(0); try { aMethod.getType().getAllExecutables(); } catch (NullPointerException e) { fail("We shoudn't have a NullPointerException when we call getAllExecutables."); } } @Test public void testSpecifyGetAllExecutablesMethod() throws Exception { final Launcher launcher = new Launcher(); launcher.setArgs(new String[] {"--output-type", "nooutput" }); launcher.addInputResource("./src/test/java/spoon/test/reference/testclasses"); launcher.run(); final CtInterface<spoon.test.reference.testclasses.Foo> foo = launcher.getFactory().Interface().get(spoon.test.reference.testclasses.Foo.class); final List<CtExecutableReference<?>> fooExecutables = foo.getAllExecutables().stream().collect(Collectors.toList()); assertEquals(1, fooExecutables.size()); assertEquals(foo.getSuperInterfaces().stream().findFirst().get().getTypeDeclaration().getMethod("m").getReference(), launcher.getFactory().Interface().get(SuperFoo.class).getMethod("m").getReference()); final CtClass<Bar> bar = launcher.getFactory().Class().get(Bar.class); final List<CtExecutableReference<?>> barExecutables = bar.getAllExecutables().stream().collect(Collectors.toList()); assertEquals(12 /* object */ + 1 /* constructor */, barExecutables.size()); final CtInterface<Kuu> kuu = launcher.getFactory().Interface().get(Kuu.class); final List<CtExecutableReference<?>> kuuExecutables = kuu.getAllExecutables().stream().collect(Collectors.toList()); assertEquals(1 /* default method in interface */, kuuExecutables.size()); assertEquals(kuu.getMethod("m").getReference(), kuuExecutables.get(0)); } @Test public void testCreateReferenceForAnonymousExecutable() { final spoon.Launcher launcher = new spoon.Launcher(); launcher.addInputResource("src/test/resources/noclasspath/Foo4.java"); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setComplianceLevel(8); launcher.buildModel(); launcher.getModel().getElements(new TypeFilter<CtExecutable<?>>(CtExecutable.class) { @Override public boolean matches(final CtExecutable<?> exec) { try { exec.getReference(); } catch (ClassCastException ex) { fail(ex.getMessage()); } return super.matches(exec); } }); } @Test public void testInvokeEnumMethod() { final spoon.Launcher launcher = new spoon.Launcher(); launcher.addInputResource("./src/test/java/spoon/test/reference/Enum.java"); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setComplianceLevel(8); launcher.buildModel(); CtInvocation invocation = launcher.getModel().getElements(new TypeFilter<CtInvocation>(CtInvocation.class) { @Override public boolean matches(CtInvocation element) { return super.matches(element) && element.getExecutable().getSimpleName().equals("valueOf"); } }).get(0); assertNotNull(invocation.getExecutable().getExecutableDeclaration()); } @Test public void testLambdaNoClasspath() { final Launcher launcher = new Launcher(); // Throws `IllegalStateException` before PR #1100 due to invalid AST // hierarchy. launcher.addInputResource("./src/test/resources/noclasspath/org/elasticsearch/action/admin/cluster/node/tasks"); launcher.getEnvironment().setNoClasspath(true); launcher.buildModel(); } }