diff --git a/src/main/java/spoon/reflect/declaration/CtTypeInformation.java b/src/main/java/spoon/reflect/declaration/CtTypeInformation.java index a5dcc4cbd55..dd6a2a323d8 100644 --- a/src/main/java/spoon/reflect/declaration/CtTypeInformation.java +++ b/src/main/java/spoon/reflect/declaration/CtTypeInformation.java @@ -115,6 +115,11 @@ public interface CtTypeInformation { /** * Returns the class type directly extended by this class. * + * getSuperClass().getDeclaration()/getTypeDeclaration() returns the corresponding CtType (if in the source folder of Spoon). + * + * However, getSuperClass().getDeclaration() returns null in very rare cases if the superclass does not use a simple name or a fully-qualified + * name based on packages, but rather an access path. + * * @return the class type directly extended by this class, or null if there * is none */ diff --git a/src/test/java/spoon/test/imports/ImportTest.java b/src/test/java/spoon/test/imports/ImportTest.java index ab2a4472a14..f01c51f453e 100644 --- a/src/test/java/spoon/test/imports/ImportTest.java +++ b/src/test/java/spoon/test/imports/ImportTest.java @@ -49,18 +49,50 @@ public class ImportTest { @Test - public void testImportOfAnInnerClassInASuperClassPackage() throws Exception { + public void testImportOfAnInnerClassInASuperClassPackageAutoImport() throws Exception { Launcher spoon = new Launcher(); - spoon.setArgs(new String[] {"--output-type", "nooutput" }); - Factory factory = spoon.createFactory(); + spoon.getEnvironment().setShouldCompile(true); + spoon.getEnvironment().setAutoImports(true); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/internal/SuperClass.java"); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/internal/ChildClass.java"); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/ClientClass.java"); + spoon.setBinaryOutputDirectory("./target/spoon/super_imports/bin"); + spoon.setSourceOutputDirectory("./target/spoon/super_imports/src"); + spoon.run(); - SpoonCompiler compiler = spoon.createCompiler(factory, SpoonResourceHelper - .resources("./src/test/java/spoon/test/imports/testclasses/internal/SuperClass.java", "./src/test/java/spoon/test/imports/testclasses/internal/ChildClass.java", - "./src/test/java/spoon/test/imports/testclasses/ClientClass.java")); + final List> classes = Query.getElements(spoon.getFactory(), new NameFilter>("ClientClass")); + + final CtClass innerClass = classes.get(0).getNestedType("InnerClass"); + String expected = "spoon.test.imports.testclasses.ClientClass.InnerClass"; + assertEquals(expected, innerClass.getReference().toString()); - compiler.build(); - final List> classes = Query.getElements(factory, new NameFilter>("ClientClass")); + expected = "spoon.test.imports.testclasses.internal.ChildClass.InnerClassProtected"; + assertEquals(expected, innerClass.getSuperclass().toString()); + assertEquals("InnerClassProtected", innerClass.getSuperclass().getSimpleName()); + + // here we specify a bug. This correct value should be SuperClass + // however; for this we would need to introduce a new property in CtTypeReference related to access path (which is a major change) + // the current behavior: + // - works in 99% of the cases + // - enables Spoon to pretty-print correct compilable code (checked by shouldCompileTrue above) + assertEquals("ChildClass", innerClass.getSuperclass().getDeclaringType().getSimpleName()); + assertEquals(null, innerClass.getSuperclass().getDeclaration()); + } + + @Test + public void testImportOfAnInnerClassInASuperClassPackageFullQualified() throws Exception { + Launcher spoon = new Launcher(); + spoon.getEnvironment().setShouldCompile(true); + spoon.getEnvironment().setAutoImports(false); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/internal/SuperClass.java"); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/internal/ChildClass.java"); + spoon.addInputResource("./src/test/java/spoon/test/imports/testclasses/ClientClass.java"); + spoon.setBinaryOutputDirectory("./target/spoon/super_imports/bin"); + spoon.setSourceOutputDirectory("./target/spoon/super_imports/src"); + spoon.run(); + + final List> classes = Query.getElements(spoon.getFactory(), new NameFilter>("ClientClass")); final CtClass innerClass = classes.get(0).getNestedType("InnerClass"); String expected = "spoon.test.imports.testclasses.ClientClass.InnerClass"; @@ -68,6 +100,14 @@ public void testImportOfAnInnerClassInASuperClassPackage() throws Exception { expected = "spoon.test.imports.testclasses.internal.ChildClass.InnerClassProtected"; assertEquals(expected, innerClass.getSuperclass().toString()); + + // here we specify a bug. This correct value should be SuperClass + // however; for this we would need to introduce a new property in CtTypeReference related to access path (which is a major change) + // the current behavior: + // - works in 99% of the cases + // - enables Spoon to pretty-print correct compilable code (checked by shouldCompileTrue above) + assertEquals("ChildClass", innerClass.getSuperclass().getDeclaringType().getSimpleName()); + assertEquals(null, innerClass.getSuperclass().getDeclaration()); } @Test diff --git a/src/test/java/spoon/test/imports/testclasses/ClientClass.java b/src/test/java/spoon/test/imports/testclasses/ClientClass.java index 9c136c95ed3..2b7df0b28f5 100644 --- a/src/test/java/spoon/test/imports/testclasses/ClientClass.java +++ b/src/test/java/spoon/test/imports/testclasses/ClientClass.java @@ -3,6 +3,6 @@ import spoon.test.imports.testclasses.internal.ChildClass; public class ClientClass extends ChildClass { - private class InnerClass extends InnerClassProtected { + private class InnerClass extends spoon.test.imports.testclasses.internal.ChildClass.InnerClassProtected { } }