Skip to content

Commit 33a7281

Browse files
committed
Merge pull request #500 from GerardPaligot/fix_type_generics
2 parents 78591a9 + 909187f commit 33a7281

File tree

6 files changed

+130
-46
lines changed

6 files changed

+130
-46
lines changed

src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,10 @@ public <T> void visitCtMethod(CtMethod<T> m) {
15071507
write("default ");
15081508
}
15091509
writeFormalTypeParameters(m.getFormalTypeParameters());
1510+
final boolean old = context.ignoreGenerics;
1511+
context.ignoreGenerics = false;
15101512
scan(m.getType());
1513+
context.ignoreGenerics = old;
15111514
write(" ");
15121515
write(m.getSimpleName());
15131516
write("(");
@@ -1928,14 +1931,9 @@ public <T> void visitCtTypeReference(CtTypeReference<T> ref) {
19281931
write(ref.getSimpleName());
19291932
} else {
19301933
if (ref.getDeclaringType() != null) {
1931-
if (!context.currentThis.contains(ref.getDeclaringType()) || ref.getModifiers().contains(ModifierKind.STATIC) || hasDeclaringTypeWithGenerics(ref)) {
1932-
if (!context.ignoreEnclosingClass) {
1933-
boolean ign = context.ignoreGenerics;
1934-
context.ignoreGenerics = false;
1935-
scan(ref.getDeclaringType());
1936-
write(".");
1937-
context.ignoreGenerics = ign;
1938-
}
1934+
if (!context.ignoreEnclosingClass) {
1935+
scan(ref.getDeclaringType());
1936+
write(".");
19391937
}
19401938
write(ref.getSimpleName());
19411939
} else {
@@ -1957,34 +1955,6 @@ public <T> void visitCtImplicitTypeReference(CtImplicitTypeReference<T> referenc
19571955
// The type is implicit, we don't print it!
19581956
}
19591957

1960-
private <T> boolean hasDeclaringTypeWithGenerics(CtTypeReference<T> reference) {
1961-
// If current reference is a class declared in a method, we don't need this hack.
1962-
if (reference.getDeclaration() == null) {
1963-
return false;
1964-
}
1965-
if (reference.getDeclaration().getParent(CtMethod.class) != null) {
1966-
return false;
1967-
}
1968-
// If the declaring type isn't a CtType, we don't need this hack.
1969-
if (reference.getDeclaringType() == null) {
1970-
return false;
1971-
}
1972-
// If current reference use generic types, we don't need this hack.
1973-
if (reference.getActualTypeArguments().size() != 0
1974-
&& reference.getDeclaringType().getActualTypeArguments().size() == 0) {
1975-
return false;
1976-
}
1977-
final CtElement declaration = reference.getDeclaringType().getDeclaration();
1978-
if (declaration == null) {
1979-
return false;
1980-
}
1981-
if (!(declaration instanceof CtType)) {
1982-
return false;
1983-
}
1984-
// Checks if the declaring type has generic types.
1985-
return ((CtType<?>) declaration).getFormalTypeParameters().size() != 0;
1986-
}
1987-
19881958
@Override
19891959
public <T> void visitCtTypeAccess(CtTypeAccess<T> typeAccess) {
19901960
enterCtExpression(typeAccess);

src/test/java/spoon/test/targeted/TargetedExpressionTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88
import spoon.reflect.code.CtFieldRead;
99
import spoon.reflect.code.CtFieldWrite;
1010
import spoon.reflect.code.CtInvocation;
11-
import spoon.reflect.code.CtReturn;
1211
import spoon.reflect.code.CtSuperAccess;
1312
import spoon.reflect.code.CtThisAccess;
1413
import spoon.reflect.code.CtTypeAccess;
1514
import spoon.reflect.declaration.CtAnonymousExecutable;
1615
import spoon.reflect.declaration.CtClass;
1716
import spoon.reflect.declaration.CtConstructor;
18-
import spoon.reflect.declaration.CtElement;
1917
import spoon.reflect.declaration.CtField;
2018
import spoon.reflect.declaration.CtMethod;
2119
import spoon.reflect.declaration.CtType;

src/test/java/spoon/test/visibility/VisibilityTest.java

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@
55
import spoon.OutputType;
66
import spoon.SpoonAPI;
77
import spoon.compiler.SpoonCompiler;
8+
import spoon.reflect.code.CtBinaryOperator;
9+
import spoon.reflect.code.CtFieldAccess;
10+
import spoon.reflect.code.CtUnaryOperator;
811
import spoon.reflect.declaration.CtClass;
912
import spoon.reflect.declaration.CtMethod;
13+
import spoon.reflect.declaration.CtType;
1014
import spoon.reflect.factory.Factory;
1115
import spoon.reflect.reference.CtFieldReference;
1216
import spoon.reflect.visitor.Query;
1317
import spoon.reflect.visitor.filter.AbstractReferenceFilter;
18+
import spoon.reflect.visitor.filter.TypeFilter;
1419
import spoon.test.TestUtils;
20+
import spoon.test.visibility.testclasses.A;
21+
import spoon.test.visibility.testclasses.A2;
1522

1623
import java.io.File;
1724
import java.util.List;
@@ -63,14 +70,48 @@ public void testVisibilityOfClassesNamedByClassesInJavaLangPackage() throws Exce
6370
}
6471

6572
@Test
66-
public void testComplexVisibilityWithGenerics() throws Exception {
73+
public void testFullyQualifiedNameOfTypeReferenceWithGeneric() throws Exception {
74+
// contract: Generics are written when there are specified in the return type of a method.
75+
final String target = "./target/spooned/spoon/test/visibility_generics/testclasses/";
6776
final SpoonAPI launcher = new Launcher();
68-
launcher.run(new String[] {
69-
"-i", "./src/test/java/spoon/test/visibility/testclasses/A.java",
70-
"-o", "./target/spooned/spoon/test/visibility_generics/testclasses/"
71-
});
77+
launcher.addInputResource("./src/test/java/spoon/test/visibility/testclasses/A.java");
78+
launcher.addInputResource("./src/test/java/spoon/test/visibility/testclasses/A2.java");
79+
launcher.addInputResource("./src/test/java/spoon/test/visibility/testclasses/Foo.java");
80+
launcher.setSourceOutputDirectory(target);
81+
launcher.run();
82+
83+
final CtClass<A> aClass = launcher.getFactory().Class().get(A.class);
84+
CtType<?> nestedB = aClass.getNestedType("B");
85+
List<CtFieldAccess> elements = nestedB.getElements(new TypeFilter<>(CtFieldAccess.class));
86+
assertEquals(1, elements.size());
87+
assertEquals("(spoon.test.visibility.testclasses.A.B.i)", elements.get(0).toString());
88+
89+
CtMethod<?> instanceOf = aClass.getMethodsByName("instanceOf").get(0);
90+
List<CtBinaryOperator> elements1 = instanceOf.getElements(new TypeFilter<>(CtBinaryOperator.class));
91+
assertEquals(1, elements1.size());
92+
assertEquals("spoon.test.visibility.testclasses.A.B", elements1.get(0).getRightHandOperand().toString());
93+
94+
CtMethod<?> returnType = aClass.getMethodsByName("returnType").get(0);
95+
assertEquals("spoon.test.visibility.testclasses.A<T>.C<T>", returnType.getType().toString());
96+
97+
final CtClass<A2> secondClass = launcher.getFactory().Class().get(A2.class);
98+
nestedB = secondClass.getNestedType("B");
99+
elements = nestedB.getElements(new TypeFilter<>(CtFieldAccess.class));
100+
assertEquals(1, elements.size());
101+
assertEquals("(spoon.test.visibility.testclasses.A2.B.i)", elements.get(0).toString());
102+
103+
instanceOf = secondClass.getMethodsByName("instanceOf").get(0);
104+
elements1 = instanceOf.getElements(new TypeFilter<>(CtBinaryOperator.class));
105+
assertEquals(1, elements1.size());
106+
assertEquals("spoon.test.visibility.testclasses.A2.B", elements1.get(0).getRightHandOperand().toString());
107+
108+
returnType = secondClass.getMethodsByName("returnType").get(0);
109+
assertEquals("spoon.test.visibility.testclasses.A2.C<java.lang.String>", returnType.getType().toString());
110+
111+
returnType = secondClass.getMethodsByName("returnType2").get(0);
112+
assertEquals("spoon.test.visibility.testclasses.Foo<java.lang.String>.Bar<java.lang.String>", returnType.getType().toString());
72113

73-
TestUtils.canBeBuilt("./target/spooned/spoon/test/visibility_generics/testclasses/", 8);
114+
TestUtils.canBeBuilt(target, 8);
74115
}
75116

76117
@Test

src/test/java/spoon/test/visibility/testclasses/A.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22

33
public class A<T> {
44
public class B {
5+
public static final int i = 0;
6+
public boolean m(Object o) {
7+
return i == 0;
8+
}
59
}
610

711
public class C<T> {
812
}
913

10-
public boolean m(Object o) {
14+
public boolean instanceOf(Object o) {
1115
return o instanceof A.B;
1216
}
1317

14-
public C<T> m() {
18+
public C<T> returnType() {
1519
return new C<T>();
1620
}
1721

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (C) 2006-2015 INRIA and contributors
3+
* Spoon - http://spoon.gforge.inria.fr/
4+
*
5+
* This software is governed by the CeCILL-C License under French law and
6+
* abiding by the rules of distribution of free software. You can use, modify
7+
* and/or redistribute the software under the terms of the CeCILL-C license as
8+
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13+
*
14+
* The fact that you are presently reading this means that you have had
15+
* knowledge of the CeCILL-C license and that you accept its terms.
16+
*/
17+
18+
package spoon.test.visibility.testclasses;
19+
20+
public class A2 {
21+
public class B {
22+
public static final int i = 0;
23+
public boolean m(Object o) {
24+
return i == 0;
25+
}
26+
}
27+
28+
public class C<T> {
29+
}
30+
31+
public boolean instanceOf(Object o) {
32+
return o instanceof A2.B;
33+
}
34+
35+
public C<String> returnType() {
36+
return new C<String>();
37+
}
38+
39+
public Foo<String>.Bar<String> returnType2(String s) {
40+
return null;
41+
}
42+
43+
public void aMethod() {
44+
class D {
45+
}
46+
new D();
47+
}
48+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (C) 2006-2015 INRIA and contributors
3+
* Spoon - http://spoon.gforge.inria.fr/
4+
*
5+
* This software is governed by the CeCILL-C License under French law and
6+
* abiding by the rules of distribution of free software. You can use, modify
7+
* and/or redistribute the software under the terms of the CeCILL-C license as
8+
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13+
*
14+
* The fact that you are presently reading this means that you have had
15+
* knowledge of the CeCILL-C license and that you accept its terms.
16+
*/
17+
18+
package spoon.test.visibility.testclasses;
19+
20+
public class Foo<T> {
21+
public class Bar<C> {
22+
}
23+
}

0 commit comments

Comments
 (0)