Skip to content

Commit

Permalink
fixes bug in printing of Implicit access to static field INRIA#914
Browse files Browse the repository at this point in the history
  • Loading branch information
pvojtechovsky committed Nov 14, 2016
1 parent a98b96d commit 90db031
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 2 deletions.
36 changes: 34 additions & 2 deletions src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package spoon.reflect.visitor;

import spoon.Launcher;
import spoon.compiler.Environment;
import spoon.reflect.code.CtAnnotationFieldAccess;
import spoon.reflect.code.CtArrayAccess;
Expand Down Expand Up @@ -1556,20 +1557,51 @@ public void visitCtWildcardReference(CtWildcardReference wildcardReference) {

private boolean printQualified(CtTypeReference<?> ref) {
if (importsContext.isImported(ref)) {
// If my.pkg.Something is imported, but we are in the context of a class which is
// also called "Something", we should still use qualified version my.pkg.Something
// If my.pkg.Something is imported, but
//A) we are in the context of a class which is also called "Something",
//B) we are in the context of a class which defines field which is also called "Something",
// we should still use qualified version my.pkg.Something
for (CtTypeReference<?> enclosingClassRef : context.currentThis) {
if (enclosingClassRef.getSimpleName().equals(ref.getSimpleName())
&& !Objects.equals(enclosingClassRef.getPackage(), ref.getPackage())) {
return true;
}
CtType<?> enclosingClass = enclosingClassRef.getDeclaration();
if (enclosingClass != null) {
CtField<?> field = getDeclareddOrInheritedField(enclosingClass, ref.getSimpleName());
if (field != null) {
return true;
}
}
}
return false;
} else {
return true;
}
}

private static CtField<?> getDeclareddOrInheritedField(CtType<?> type, String fieldName) {
if (type == null) {
return null;
}
CtField<?> field = type.getField(fieldName);
if (field != null) {
return field;
}
CtTypeReference<?> str = type.getSuperclass();
if (str != null) {
CtType<?> st;
try {
st = str.getTypeDeclaration();
} catch (Throwable e) {
Launcher.LOGGER.error("cannot determine runtime type for (" + type.getQualifiedName() + ")", e);
return null;
}
return getDeclareddOrInheritedField(st, fieldName);
}
return null;
}

@Override
public <T> void visitCtIntersectionTypeReference(CtIntersectionTypeReference<T> reference) {
for (CtTypeReference<?> bound : reference.getBounds()) {
Expand Down
6 changes: 6 additions & 0 deletions src/test/java/spoon/test/staticFieldAccess2/ALong.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package spoon.test.staticFieldAccess2;

public @interface ALong
{
public long number() default 7;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package spoon.test.staticFieldAccess2;

public class AmbiguousImplicitFieldReference {
/*
* The static field has exactly same name like the Class name.
* for example Apache CXF generates classes like that
*/
public static String AmbiguousImplicitFieldReference = "c1";
public String memberField;

public String getMemberField() {
return memberField;
}

public void setMemberField(String p_memberField) {
memberField = p_memberField;
}
public void setMemberField2(String memberField) {
this.memberField = memberField;
}

public void testLocalMethodInvocations() {
getMemberField();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package spoon.test.staticFieldAccess2;

//the PRIO must be prefixed by Constants because we are not yet in scope of Constants class
@ALong(number = Constants.PRIO)
public class ChildOfConstants extends Constants
{
long p1 = Constants.PRIO;
long p2 = PRIO;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package spoon.test.staticFieldAccess2;

public class ChildOfGenericsWithAmbiguousStaticField extends GenericsWithAmbiguousStaticField
{

public <V, C extends java.util.List<V>> void m1() {
spoon.test.staticFieldAccess2.GenericsWithAmbiguousStaticField.<V, C>genericMethod();
genericMethod();
}

}
6 changes: 6 additions & 0 deletions src/test/java/spoon/test/staticFieldAccess2/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package spoon.test.staticFieldAccess2;

public class Constants
{
public static final long PRIO = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package spoon.test.staticFieldAccess2;

public class GenericsWithAmbiguousMemberField {

String GenericsWithAmbiguousMemberField = "x";

public <V, C extends java.util.List<V>> void m1() {
spoon.test.staticFieldAccess2.GenericsWithAmbiguousMemberField.<V, C>genericMethod();
GenericsWithAmbiguousMemberField.length();
genericMethod();
}

public static <V, C extends java.util.List<V>> java.util.List<C> genericMethod() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package spoon.test.staticFieldAccess2;

public class GenericsWithAmbiguousStaticField {

static String GenericsWithAmbiguousStaticField = "x";

public <V, C extends java.util.List<V>> void m1() {
spoon.test.staticFieldAccess2.GenericsWithAmbiguousStaticField.<V, C>genericMethod();
genericMethod();
}

public static <V, C extends java.util.List<V>> java.util.List<C> genericMethod() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package spoon.test.staticFieldAccess2;

public class ImplicitFieldReference {
public String memberField;

public String getMemberField() {
return memberField;
}

public void setMemberField(String p_memberField) {
memberField = p_memberField;
}
public void setMemberField2(String memberField) {
this.memberField = memberField;
}

public void testLocalMethodInvocations() {
getMemberField();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package spoon.test.staticFieldAccess2;

public class ImplicitStaticClassAccess {
static String ImplicitStaticClassAccess = "";

ImplicitStaticClassAccess() {
this(ImplicitStaticClassAccess.class);
}

ImplicitStaticClassAccess(Class<?> clazz) {
ImplicitStaticClassAccess.class.getName();
}

public void testLocalMethodInvocations() {
ImplicitStaticClassAccess.class.getName();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package spoon.test.staticFieldAccess2;


public class ImplicitStaticFieldReference {
/*
* The static field has exactly same name like the Class name.
* for example Apache CXF generates classes like that
*/
public static String ImplicitStaticFieldReference = "c1";
public static long staticField = Constants.PRIO;

public String reader() {
return ImplicitStaticFieldReference;
}

public void writer(String value) {
ImplicitStaticFieldReference = value;
}

public static long longReader() {
return staticField;
}

public static void longWriter(long value) {
staticField = value;
}

public void testLocalMethodInvocations() {
reader();
longWriter(7);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package spoon.test.staticFieldAccess2;

import static spoon.testing.utils.ModelUtils.canBeBuilt;

import static org.junit.Assert.*;
import org.junit.Test;

import spoon.Launcher;
import spoon.reflect.declaration.CtClass;

public class ImplicitStaticFieldReferenceTest
{
private static final boolean expectImplicit = false;

@Test
public void testImplicitStaticFieldReference() throws Exception {
Launcher launcher = checkFile(false, "ImplicitStaticFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(ImplicitStaticFieldReference.class);
assertEquals("return ImplicitStaticFieldReference", cls.getMethod("reader").getBody().getStatements().get(0).toString());
assertEquals("ImplicitStaticFieldReference = value", cls.getMethodsByName("writer").get(0).getBody().getStatements().get(0).toString());
assertEquals("reader()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
assertEquals("longWriter(7)", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(1).toString());
}
}

@Test
public void testImplicitStaticFieldReferenceAutoImport() throws Exception {
Launcher launcher = checkFile(true, "ImplicitStaticFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(ImplicitStaticFieldReference.class);
assertEquals("return ImplicitStaticFieldReference", cls.getMethod("reader").getBody().getStatements().get(0).toString());
assertEquals("ImplicitStaticFieldReference = value", cls.getMethodsByName("writer").get(0).getBody().getStatements().get(0).toString());
assertEquals("reader()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
assertEquals("longWriter(7)", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(1).toString());
}
}

@Test
public void testImplicitFieldReference() throws Exception {
Launcher launcher = checkFile(false, "ImplicitFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(ImplicitFieldReference.class);
assertEquals("return memberField", cls.getMethod("getMemberField").getBody().getStatements().get(0).toString());
assertEquals("memberField = p_memberField", cls.getMethodsByName("setMemberField").get(0).getBody().getStatements().get(0).toString());
// assertEquals("this.memberField = memberField", cls.getMethodsByName("setMemberField2").get(0).getBody().getStatements().get(0).toString());
assertEquals("getMemberField()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
}
}
@Test
public void testImplicitFieldReferenceAutoImport() throws Exception {
Launcher launcher = checkFile(true, "ImplicitFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(ImplicitFieldReference.class);
assertEquals("return memberField", cls.getMethod("getMemberField").getBody().getStatements().get(0).toString());
assertEquals("memberField = p_memberField", cls.getMethodsByName("setMemberField").get(0).getBody().getStatements().get(0).toString());
// assertEquals("this.memberField = memberField", cls.getMethodsByName("setMemberField2").get(0).getBody().getStatements().get(0).toString());
assertEquals("getMemberField()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
}
}

@Test
public void testAmbiguousImplicitFieldReference() throws Exception {
Launcher launcher = checkFile(false, "AmbiguousImplicitFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(AmbiguousImplicitFieldReference.class);
assertEquals("return memberField", cls.getMethod("getMemberField").getBody().getStatements().get(0).toString());
assertEquals("memberField = p_memberField", cls.getMethodsByName("setMemberField").get(0).getBody().getStatements().get(0).toString());
// assertEquals("this.memberField = memberField", cls.getMethodsByName("setMemberField2").get(0).getBody().getStatements().get(0).toString());
assertEquals("getMemberField()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
}
}
@Test
public void testAmbiguousImplicitFieldReferenceAutoImport() throws Exception {
Launcher launcher = checkFile(true, "AmbiguousImplicitFieldReference.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(AmbiguousImplicitFieldReference.class);
assertEquals("return memberField", cls.getMethod("getMemberField").getBody().getStatements().get(0).toString());
assertEquals("memberField = p_memberField", cls.getMethodsByName("setMemberField").get(0).getBody().getStatements().get(0).toString());
// assertEquals("this.memberField = memberField", cls.getMethodsByName("setMemberField2").get(0).getBody().getStatements().get(0).toString());
assertEquals("getMemberField()", cls.getMethodsByName("testLocalMethodInvocations").get(0).getBody().getStatements().get(0).toString());
}
}

@Test
public void testImplicitStaticClassAccess() throws Exception {
Launcher launcher = checkFile(false, "ImplicitStaticClassAccess.java");
}
@Test
public void testImplicitStaticClassAccessAutoImport() throws Exception {
Launcher launcher = checkFile(true, "ImplicitStaticClassAccess.java");
}
@Test
public void testGenericsWithAmbiguousStaticField() throws Exception {
Launcher launcher = checkFile(false, "GenericsWithAmbiguousStaticField.java");
}
@Test
public void testGenericsWithAmbiguousStaticFieldAutoImport() throws Exception {
Launcher launcher = checkFile(true, "GenericsWithAmbiguousStaticField.java");
}

@Test
public void testChildOfGenericsWithAmbiguousStaticField() throws Exception {
Launcher launcher = checkFile(false, "ChildOfGenericsWithAmbiguousStaticField.java");
}

@Test
public void testChildOfGenericsWithAmbiguousStaticFieldAutoImport() throws Exception {
Launcher launcher = checkFile(true, "ChildOfGenericsWithAmbiguousStaticField.java");
if(expectImplicit) {
CtClass<?> cls = launcher.getFactory().Class().get(ChildOfGenericsWithAmbiguousStaticField.class);
//The toString of the method does not have a context of class, so it different result
// assertEquals("spoon.test.staticFieldAccess2.GenericsWithAmbiguousStaticField.<V, C>genericMethod()", cls.getMethod("m1").getBody().getStatements().get(0).toString());
assertTrue(cls.toString().indexOf("spoon.test.staticFieldAccess2.GenericsWithAmbiguousStaticField.<V, C>genericMethod()")>=0);
assertEquals("genericMethod()", cls.getMethod("m1").getBody().getStatements().get(1).toString());
}
}

@Test
public void testGenericsWithAmbiguousMemberField() throws Exception {
Launcher launcher = checkFile(false, "GenericsWithAmbiguousMemberField.java");
}
@Test
public void testGenericsWithAmbiguousMemberFieldAutoImport() throws Exception {
Launcher launcher = checkFile(true, "GenericsWithAmbiguousMemberField.java");
}

@Test
public void testAnnotationInChildWithConstants() throws Exception {
Launcher launcher = checkFile(false, "ChildOfConstants.java", "Constants.java");
}

@Test
public void testAnnotationInChildWithConstantsAutoImport() throws Exception {
Launcher launcher = checkFile(true, "ChildOfConstants.java", "Constants.java");
}

private static Launcher checkFile(boolean autoImports, String... fileName) {
Launcher launcher = new Launcher();
launcher.getEnvironment().setAutoImports(autoImports);

String pckg = "spoon/test/staticFieldAccess2/";
for (String fn : fileName)
{
launcher.addInputResource("src/test/java/"+pckg+fn);
}
String targetDir = "./target/spooned"+(autoImports?"-autoImports":"");
launcher.setSourceOutputDirectory(targetDir);
launcher.buildModel();
launcher.prettyprint();
for (String fn : fileName)
{
canBeBuilt(targetDir+"/"+pckg+fn, 8);
}
return launcher;
}
}

0 comments on commit 90db031

Please sign in to comment.