Skip to content

Commit

Permalink
fix: fix bug related to generics in CtTypeReference in noclasspath (#…
Browse files Browse the repository at this point in the history
…1609)

Close #1607
  • Loading branch information
surli authored and monperrus committed Oct 17, 2017
1 parent 3cd7a26 commit e620e69
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,9 @@ private boolean createParameterizedType(TypeReference parameterizedTypeReference
if (skipTypeInAnnotation) {
return true;
}
context.enter(factory.Code().createTypeAccessWithoutCloningReference(references.buildTypeReference(parameterizedTypeReference, null)), parameterizedTypeReference);
CtTypeReference typeReference = references.buildTypeReference(parameterizedTypeReference, null);
CtTypeAccess typeAccess = factory.Code().createTypeAccessWithoutCloningReference(typeReference);
context.enter(typeAccess, parameterizedTypeReference);
return true;
}

Expand Down
16 changes: 11 additions & 5 deletions src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ <T> CtTypeReference<T> buildTypeReference(TypeReference type, Scope scope) {
if (type == null) {
return null;
}
return buildTypeReferenceInternal(this.<T>getTypeReference(type.resolvedType, type), type, scope);
CtTypeReference<T> typeReference = this.<T>getTypeReference(type.resolvedType, type);
return buildTypeReferenceInternal(typeReference, type, scope);
}

/**
Expand Down Expand Up @@ -457,7 +458,8 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding, TypeReference ref)
insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef);
return ctRef;
}
return getTypeReference(ref);
CtTypeReference<T> result = getTypeReference(ref);
return result;
}

CtTypeReference<Object> getTypeParameterReference(TypeBinding binding, TypeReference ref) {
Expand Down Expand Up @@ -518,6 +520,9 @@ <T> CtTypeReference<T> getTypeReference(TypeReference ref) {
CtTypeReference<T> res = null;
CtTypeReference inner = null;
final String[] namesParameterized = CharOperation.charArrayToStringArray(ref.getParameterizedTypeName());
String nameParameterized = CharOperation.toString(ref.getParameterizedTypeName());
String typeName = CharOperation.toString(ref.getTypeName());

int index = namesParameterized.length - 1;
for (; index >= 0; index--) {
// Start at the end to get the class name first.
Expand All @@ -533,16 +538,17 @@ <T> CtTypeReference<T> getTypeReference(TypeReference ref) {
inner = main;
}
if (res == null) {
return this.jdtTreeBuilder.getFactory().Type().createReference(CharOperation.toString(ref.getParameterizedTypeName()));
return this.jdtTreeBuilder.getFactory().Type().createReference(nameParameterized);
}

if (inner.getPackage() == null) {
PackageFactory packageFactory = this.jdtTreeBuilder.getFactory().Package();
CtPackageReference packageReference = index >= 0 ? packageFactory.getOrCreate(concatSubArray(namesParameterized, index)).getReference() : packageFactory.topLevel();
inner.setPackage(packageReference);
}
if (!res.toString().replace(", ?", ",?").endsWith(CharOperation.toString(ref.getParameterizedTypeName()))) {
if (!res.toString().replace(", ?", ",?").endsWith(nameParameterized)) {
// verify that we did not match a class that have the same name in a different package
return this.jdtTreeBuilder.getFactory().Type().createReference(CharOperation.toString(ref.getParameterizedTypeName()));
return this.jdtTreeBuilder.getFactory().Type().createReference(typeName);
}
return res;
}
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/spoon/test/imports/ImportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1230,4 +1230,26 @@ public void testImportStarredPackageWithNonVisibleClass() throws IOException {

assertEquals(3, cu.getImports().size());
}

@Test
public void testImportWithGenerics() throws IOException {
// contract: in noclasspath autoimport, we should be able to use generic type
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/import-with-generics/TestWithGenerics.java");
launcher.getEnvironment().setAutoImports(true);
launcher.getEnvironment().setShouldCompile(true);
launcher.getEnvironment().setNoClasspath(true);
launcher.setSourceOutputDirectory("./target/import-with-generics");
launcher.run();

PrettyPrinter prettyPrinter = launcher.createPrettyPrinter();
CtType element = launcher.getFactory().Class().get("spoon.test.imports.testclasses.TestWithGenerics");
List<CtType<?>> toPrint = new ArrayList<>();
toPrint.add(element);

prettyPrinter.calculate(element.getPosition().getCompilationUnit(), toPrint);
String output = prettyPrinter.getResult();

assertTrue(output.contains("import spoon.test.imports.testclasses.withgenerics.Target;"));
}
}
16 changes: 16 additions & 0 deletions src/test/java/spoon/test/reference/TypeReferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -623,4 +623,20 @@ public void testEqualityTypeReference() throws Exception {

assertEquals(parameterRef1, parameterRef2);
}

@Test
public void testTypeReferenceWithGenerics() throws Exception {
// contract: in noclasspath, a generic type name should not contain generic information
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/import-with-generics/TestWithGenerics.java");
launcher.getEnvironment().setAutoImports(true);
launcher.getEnvironment().setNoClasspath(true);
launcher.buildModel();

CtField field = launcher.getModel().getElements(new TypeFilter<CtField>(CtField.class)).get(0);
CtTypeReference fieldTypeRef = field.getType();

assertEquals("spoon.test.imports.testclasses.withgenerics.Target", fieldTypeRef.getQualifiedName());
assertEquals(2, fieldTypeRef.getActualTypeArguments().size());
}
}
7 changes: 7 additions & 0 deletions src/test/resources/import-with-generics/TestWithGenerics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package spoon.test.imports.testclasses;
/**
* Created by urli on 16/10/2017.
*/
public class TestWithGenerics {
public spoon.test.imports.testclasses.withgenerics.Target<Object, Object> myfields;
}

0 comments on commit e620e69

Please sign in to comment.