From 47310699abb05eb11e1af93214be6dabcf19a639 Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Mon, 26 Sep 2016 11:17:15 +0200 Subject: [PATCH] fix(isLocalType): proper support for creating internal classes (fixes #776) --- .../reflect/declaration/CtTypeImpl.java | 29 ++++++----- .../reference/CtTypeReferenceImpl.java | 31 ++++++------ .../java/spoon/test/ctClass/CtClassTest.java | 50 +++++++++++++++---- 3 files changed, 74 insertions(+), 36 deletions(-) diff --git a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java index 28b795b875b..cbb5af29c72 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java @@ -16,6 +16,20 @@ */ package spoon.support.reflect.declaration; +import static spoon.reflect.ModelElementContainerDefaultCapacities.TYPE_TYPE_PARAMETERS_CONTAINER_DEFAULT_CAPACITY; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +import spoon.reflect.code.CtBlock; import spoon.reflect.cu.CompilationUnit; import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtAnnotationType; @@ -47,18 +61,6 @@ import spoon.support.util.QualifiedNameBasedSortedSet; import spoon.support.util.SignatureBasedSortedSet; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static spoon.reflect.ModelElementContainerDefaultCapacities.TYPE_TYPE_PARAMETERS_CONTAINER_DEFAULT_CAPACITY; - /** * The implementation for {@link spoon.reflect.declaration.CtType}. */ @@ -446,7 +448,8 @@ public boolean isAnonymous() { @Override public boolean isLocalType() { - return getReference().isLocalType(); + return Pattern.compile("^([0-9]+)([a-zA-Z]+)$").matcher(getSimpleName()).find() + || (isParentInitialized() && getParent() instanceof CtBlock); } @Override diff --git a/src/main/java/spoon/support/reflect/reference/CtTypeReferenceImpl.java b/src/main/java/spoon/support/reflect/reference/CtTypeReferenceImpl.java index 347f750c0c1..5f5500251fc 100644 --- a/src/main/java/spoon/support/reflect/reference/CtTypeReferenceImpl.java +++ b/src/main/java/spoon/support/reflect/reference/CtTypeReferenceImpl.java @@ -16,6 +16,20 @@ */ package spoon.support.reflect.reference; +import static spoon.reflect.ModelElementContainerDefaultCapacities.TYPE_TYPE_PARAMETERS_CONTAINER_DEFAULT_CAPACITY; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import spoon.Launcher; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtPackage; @@ -35,20 +49,6 @@ import spoon.support.util.QualifiedNameBasedSortedSet; import spoon.support.util.RtHelper; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static spoon.reflect.ModelElementContainerDefaultCapacities.TYPE_TYPE_PARAMETERS_CONTAINER_DEFAULT_CAPACITY; - public class CtTypeReferenceImpl extends CtReferenceImpl implements CtTypeReference { private static final long serialVersionUID = 1L; @@ -499,6 +499,9 @@ public boolean isAnonymous() { @Override public boolean isLocalType() { + if (this.getDeclaration() != null) { + return (this.getDeclaration().isLocalType()); + } // A local type doesn't have a fully qualified name but have an identifier // to know which is the local type member wanted by the developer. // Oracle documentation: https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.7 diff --git a/src/test/java/spoon/test/ctClass/CtClassTest.java b/src/test/java/spoon/test/ctClass/CtClassTest.java index ab36eb329bb..9b563b909ed 100644 --- a/src/test/java/spoon/test/ctClass/CtClassTest.java +++ b/src/test/java/spoon/test/ctClass/CtClassTest.java @@ -1,25 +1,29 @@ package spoon.test.ctClass; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static spoon.testing.utils.ModelUtils.build; +import static spoon.testing.utils.ModelUtils.buildClass; +import static spoon.testing.utils.ModelUtils.canBeBuilt; + +import java.util.Set; + import org.junit.Test; + import spoon.Launcher; +import spoon.reflect.code.CtBlock; +import spoon.reflect.code.CtConstructorCall; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtConstructor; import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.ModifierKind; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtTypeReference; import spoon.test.ctClass.testclasses.Foo; import spoon.test.ctClass.testclasses.Pozole; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static spoon.testing.utils.ModelUtils.build; -import static spoon.testing.utils.ModelUtils.buildClass; -import static spoon.testing.utils.ModelUtils.canBeBuilt; - public class CtClassTest { @Test @@ -102,5 +106,33 @@ public void testAllTypeReferencesToALocalTypeShouldNotStartWithNumber() throws E final String expectedConstructor = "public Cook() {" + System.lineSeparator() + "}"; assertEquals(expectedConstructor, constructors.toArray(new CtConstructor[constructors.size()])[0].toString()); assertEquals("final java.lang.Class cookClass = Cook.class", cook.getMethod("m").getBody().getStatement(0).toString()); + + Factory factory = aPozole.getFactory(); + + aPozole.removeModifier(ModifierKind.PUBLIC); + factory.Code().createCodeSnippetStatement(aPozole.toString()).compile(); + + CtClass internalClass = factory.Core().createClass(); + internalClass.setSimpleName("Foo"); + cook.getParent(CtBlock.class).addStatement(internalClass); + assertEquals("Foo", internalClass.getSimpleName()); + assertEquals("spoon.test.ctClass.testclasses.Pozole$Foo", internalClass.getQualifiedName()); + + internalClass.addConstructor(factory.Core().createConstructor()); + CtConstructor cons = (CtConstructor) internalClass.getConstructors().toArray(new CtConstructor[0])[0]; + cons.setBody(factory.Core().createBlock()); + + CtConstructorCall call = cook.getFactory().Core().createConstructorCall(); + call.setExecutable(cons.getReference()); + assertEquals(internalClass, internalClass.getReference().getDeclaration()); + assertEquals("new Foo()", call.toString()); + internalClass.insertAfter(call); + + factory.getEnvironment().setAutoImports(true); + factory.Code().createCodeSnippetStatement(aPozole.toString()).compile(); + + factory.getEnvironment().setAutoImports(false); + factory.Code().createCodeSnippetStatement(aPozole.toString()).compile(); + } }