diff --git a/src/main/java/spoon/reflect/declaration/CtType.java b/src/main/java/spoon/reflect/declaration/CtType.java index 9d80aec0b68..6018c297c19 100644 --- a/src/main/java/spoon/reflect/declaration/CtType.java +++ b/src/main/java/spoon/reflect/declaration/CtType.java @@ -32,6 +32,10 @@ public interface CtType extends CtNamedElement, CtTypeInformation, CtTypeMemb * The string separator in a Java innertype qualified name. */ String INNERTTYPE_SEPARATOR = "$"; + /** + * Used in no classpath when we don't have any information to build the name of the type. + */ + String NAME_UNKNOWN = ""; /** * Returns the simple (unqualified) name of this element. diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 83c06cd0d5b..efdfa1a6c63 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -3379,6 +3379,7 @@ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) { if (localTypeDeclaration.binding == null) { // no classpath mode but JDT returns nothing. We create an empty class. t = factory.Core().createClass(); + t.setSimpleName(CtType.NAME_UNKNOWN); ((CtClass) t).setSuperclass(references.getTypeReference(null, localTypeDeclaration.allocation.type)); } else { t = createType(localTypeDeclaration); diff --git a/src/test/java/spoon/test/constructorcallnewclass/NewClassTest.java b/src/test/java/spoon/test/constructorcallnewclass/NewClassTest.java index 2cd23dc9604..89f67012999 100644 --- a/src/test/java/spoon/test/constructorcallnewclass/NewClassTest.java +++ b/src/test/java/spoon/test/constructorcallnewclass/NewClassTest.java @@ -6,6 +6,7 @@ import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtNewClass; import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; @@ -161,7 +162,7 @@ public void testCtNewClassInNoClasspath() throws Exception { assertEquals("Lock$With", anonymousClass.getSuperclass().getQualifiedName()); assertEquals("Lock", anonymousClass.getSuperclass().getDeclaringType().getSimpleName()); assertEquals("Lock.With", anonymousClass.getSuperclass().toString()); - assertNull(anonymousClass.getSimpleName()); // In noclasspath, we don't have this information. + assertEquals(CtType.NAME_UNKNOWN, anonymousClass.getSimpleName()); // In noclasspath, we don't have this information. assertEquals(1, anonymousClass.getMethods().size()); TestUtils.canBeBuilt("./target/new-class", 8, true); diff --git a/src/test/java/spoon/test/reference/TypeReferenceTest.java b/src/test/java/spoon/test/reference/TypeReferenceTest.java index 2dbfa094cbb..120e9824796 100644 --- a/src/test/java/spoon/test/reference/TypeReferenceTest.java +++ b/src/test/java/spoon/test/reference/TypeReferenceTest.java @@ -412,6 +412,21 @@ public void testAnnotationOnMethodWithPrimitiveReturnTypeInNoClasspath() throws assertEquals("@Override" + System.lineSeparator(), run.getAnnotations().get(0).toString()); } + @Test + public void testAnonymousClassesHaveAnEmptyStringForItsNameInNoClasspath() throws Exception { + // contract: In no classpath mode, a type reference have an empty string for its name. + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/A.java"); + launcher.setSourceOutputDirectory("./target/class-declaration"); + launcher.getEnvironment().setNoClasspath(true); + launcher.run(); + + final CtClass aClass = launcher.getFactory().Class().get("A"); + final CtClass anonymousClass = aClass.getElements(new TypeFilter<>(CtNewClass.class)).get(0).getAnonymousClass(); + assertEquals(CtType.NAME_UNKNOWN, anonymousClass.getReference().getSimpleName()); + assertEquals(7, aClass.getReferencedTypes().size()); + } + class A { class Tacos { }