From 6f5f1726ee400a58cbd4a63043547b97f734fb19 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Fri, 8 Jan 2016 15:49:13 +0100 Subject: [PATCH] fix(noclasspath): Gets package of types in the class declaration. Closes #465 --- .../support/compiler/jdt/JDTTreeBuilder.java | 39 ++++++++++++++----- .../test/reference/TypeReferenceTest.java | 28 ++++++++++++- .../java/spoon/test/variable/AccessTest.java | 2 +- src/test/resources/noclasspath/Demo.java | 3 +- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index a070669d9d9..224f3a0df2f 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -732,6 +732,10 @@ public CtTypeReference getTypeReference(TypeBinding binding) { ref = factory.Core().createTypeReference(); } ref.setSimpleName(new String(binding.readableName())); + final CtReference declaring = references.getDeclaringReferenceFromImports(binding.sourceName()); + if (declaring instanceof CtPackageReference) { + ref.setPackage((CtPackageReference) declaring); + } } else if (binding instanceof SpoonReferenceBinding) { ref = factory.Core().createTypeReference(); ref.setSimpleName(new String(binding.sourceName())); @@ -1024,7 +1028,9 @@ CtType createType(TypeDeclaration typeDeclaration) { CtEnum e = factory.Core().createEnum(); if (typeDeclaration.superInterfaces != null) { for (TypeReference ref : typeDeclaration.superInterfaces) { - e.addSuperInterface(references.getTypeReference(ref.resolvedType)); + final CtTypeReference currentInterface = references.getTypeReference(ref.resolvedType); + e.addSuperInterface(currentInterface); + insertGenericTypesInNoClasspathFromJDTInSpoon(ref, currentInterface); } } type = e; @@ -1032,7 +1038,9 @@ CtType createType(TypeDeclaration typeDeclaration) { CtInterface interf = factory.Core().createInterface(); if (typeDeclaration.superInterfaces != null) { for (TypeReference ref : typeDeclaration.superInterfaces) { - interf.addSuperInterface(references.getTypeReference(ref.resolvedType)); + final CtTypeReference currentInterface = references.getTypeReference(ref.resolvedType); + interf.addSuperInterface(currentInterface); + insertGenericTypesInNoClasspathFromJDTInSpoon(ref, currentInterface); } } if (typeDeclaration.typeParameters != null) { @@ -1060,7 +1068,9 @@ CtType createType(TypeDeclaration typeDeclaration) { } } if (typeDeclaration.superclass != null) { - cl.setSuperclass(references.getTypeReference(typeDeclaration.superclass.resolvedType)); + final CtTypeReference superClass = references.getTypeReference(typeDeclaration.superclass.resolvedType); + cl.setSuperclass(superClass); + insertGenericTypesInNoClasspathFromJDTInSpoon(typeDeclaration.superclass, superClass); } // If the current class is an anonymous class with a super interface and generic types, we add generic @@ -1080,7 +1090,9 @@ CtType createType(TypeDeclaration typeDeclaration) { if (typeDeclaration.superInterfaces != null) { for (TypeReference ref : typeDeclaration.superInterfaces) { - cl.addSuperInterface(references.getTypeReference(ref.resolvedType)); + final CtTypeReference currentInterface = references.getTypeReference(ref.resolvedType); + cl.addSuperInterface(currentInterface); + insertGenericTypesInNoClasspathFromJDTInSpoon(ref, currentInterface); } } if (typeDeclaration.typeParameters != null) { @@ -1108,6 +1120,16 @@ CtType createType(TypeDeclaration typeDeclaration) { return type; } + private void insertGenericTypesInNoClasspathFromJDTInSpoon(TypeReference original, CtTypeReference type) { + if (original.resolvedType instanceof ProblemReferenceBinding && original.getTypeArguments() != null) { + for (TypeReference[] typeReferences : original.getTypeArguments()) { + for (TypeReference typeReference : typeReferences) { + type.addActualTypeArgument(references.getTypeReference(typeReference.resolvedType)); + } + } + } + } + class SpoonReferenceBinding extends ReferenceBinding { private ReferenceBinding enclosingType; @@ -3232,19 +3254,18 @@ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope return true; } else { - CtType type = createType(typeDeclaration); - - type.setDocComment(getJavaDoc(typeDeclaration.javadoc, scope.referenceContext)); - CtPackage pack = null; if (typeDeclaration.binding.fPackage.shortReadableName() != null && typeDeclaration.binding.fPackage.shortReadableName().length > 0) { pack = factory.Package().getOrCreate(new String(typeDeclaration.binding.fPackage.shortReadableName())); } else { pack = factory.Package().getOrCreate(CtPackage.TOP_LEVEL_PACKAGE_NAME); } - pack.addType(type); context.enter(pack, typeDeclaration); context.compilationunitdeclaration = scope.referenceContext; + CtType type = createType(typeDeclaration); + pack.addType(type); + + type.setDocComment(getJavaDoc(typeDeclaration.javadoc, scope.referenceContext)); context.enter(type, typeDeclaration); // AST bug HACK diff --git a/src/test/java/spoon/test/reference/TypeReferenceTest.java b/src/test/java/spoon/test/reference/TypeReferenceTest.java index 6d66ed290c9..01c64b916c1 100644 --- a/src/test/java/spoon/test/reference/TypeReferenceTest.java +++ b/src/test/java/spoon/test/reference/TypeReferenceTest.java @@ -262,7 +262,7 @@ public void testRecursiveTypeReferenceInGenericType() throws Exception { public void testPackageInNoClasspath () { final Launcher launcher = new Launcher(); launcher.addInputResource("./src/test/resources/noclasspath/Demo.java"); - launcher.setSourceOutputDirectory("./target/class"); + launcher.setSourceOutputDirectory("./target/class-declaration"); launcher.getEnvironment().setNoClasspath(true); launcher.run(); @@ -292,6 +292,32 @@ public void testPackageInNoClasspath () { assertTrue("Reference to Joiner is missing", containsJoinerReference); } + @Test + public void testTypeReferenceSpecifiedInClassDeclarationInNoClasspath() throws Exception { + // contract: Gets the import of a type specified in the declaration of a class. + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/Demo.java"); + launcher.setSourceOutputDirectory("./target/class-declaration"); + launcher.getEnvironment().setNoClasspath(true); + launcher.run(); + + final CtClass aClass = launcher.getFactory().Class().get("Demo"); + + assertNotNull(aClass.getSuperclass()); + assertEquals("com.google.common.base.Function", aClass.getSuperclass().getQualifiedName()); + assertEquals(2, aClass.getSuperclass().getActualTypeArguments().size()); + assertEquals("java.lang.String", aClass.getSuperclass().getActualTypeArguments().get(0).toString()); + assertEquals("java.lang.String", aClass.getSuperclass().getActualTypeArguments().get(1).toString()); + + assertEquals(1, aClass.getSuperInterfaces().size()); + for (CtTypeReference superInterface : aClass.getSuperInterfaces()) { + assertEquals("com.google.common.base.Function", superInterface.getQualifiedName()); + assertEquals(2, superInterface.getActualTypeArguments().size()); + assertEquals("java.lang.String", superInterface.getActualTypeArguments().get(0).toString()); + assertEquals("java.lang.String", superInterface.getActualTypeArguments().get(1).toString()); + } + } + class A { class Tacos { } diff --git a/src/test/java/spoon/test/variable/AccessTest.java b/src/test/java/spoon/test/variable/AccessTest.java index 2e1cf2e5b26..6db08f21a8d 100644 --- a/src/test/java/spoon/test/variable/AccessTest.java +++ b/src/test/java/spoon/test/variable/AccessTest.java @@ -193,6 +193,6 @@ public void testVariableAccessInNoClasspath() throws Exception { } assertEquals("java.lang.Class mclass = ((java.lang.Class)(org.argouml.model.ModelFacade.USE_CASE))", elements.get(0).getParent().toString()); - assertEquals("new PropPanelButton(this , buttonPanel , _navUpIcon , org.argouml.i18n.Translator.localize(\"UMLMenu\", \"button.go-up\") , \"navigateNamespace\" , null)", elements.get(2).getParent().toString()); + assertEquals("new org.argouml.uml.ui.PropPanelButton(this , buttonPanel , _navUpIcon , org.argouml.i18n.Translator.localize(\"UMLMenu\", \"button.go-up\") , \"navigateNamespace\" , null)", elements.get(2).getParent().toString()); } } diff --git a/src/test/resources/noclasspath/Demo.java b/src/test/resources/noclasspath/Demo.java index 8834c70b8df..5ec0dd71bdb 100644 --- a/src/test/resources/noclasspath/Demo.java +++ b/src/test/resources/noclasspath/Demo.java @@ -1,6 +1,7 @@ import com.google.common.base.Joiner; +import com.google.common.base.Function; -public class Demo { +public class Demo extends Function implements Function { public static void main(String[] args) { Joiner.on();