Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal to fix #972 #1021

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 21 additions & 58 deletions src/main/java/spoon/support/compiler/jdt/ParentExiter.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,68 +37,14 @@
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import spoon.reflect.code.BinaryOperatorKind;
import spoon.reflect.code.CtArrayAccess;
import spoon.reflect.code.CtArrayRead;
import spoon.reflect.code.CtArrayWrite;
import spoon.reflect.code.CtAssert;
import spoon.reflect.code.CtAssignment;
import spoon.reflect.code.CtBinaryOperator;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtCase;
import spoon.reflect.code.CtCatch;
import spoon.reflect.code.CtCatchVariable;
import spoon.reflect.code.CtConditional;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.code.CtDo;
import spoon.reflect.code.CtExecutableReferenceExpression;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFor;
import spoon.reflect.code.CtForEach;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLambda;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtLoop;
import spoon.reflect.code.CtNewArray;
import spoon.reflect.code.CtNewClass;
import spoon.reflect.code.CtReturn;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtSuperAccess;
import spoon.reflect.code.CtSwitch;
import spoon.reflect.code.CtSynchronized;
import spoon.reflect.code.CtTargetedExpression;
import spoon.reflect.code.CtThisAccess;
import spoon.reflect.code.CtThrow;
import spoon.reflect.code.CtTry;
import spoon.reflect.code.CtTryWithResource;
import spoon.reflect.code.CtTypeAccess;
import spoon.reflect.code.CtUnaryOperator;
import spoon.reflect.code.CtWhile;
import spoon.reflect.declaration.CtAnnotatedElementType;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtAnnotationMethod;
import spoon.reflect.declaration.CtAnonymousExecutable;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtEnum;
import spoon.reflect.declaration.CtEnumValue;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtFormalTypeDeclarer;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypeParameter;
import spoon.reflect.declaration.CtTypedElement;
import spoon.reflect.declaration.CtVariable;
import spoon.reflect.code.*;
import spoon.reflect.declaration.*;
import spoon.reflect.reference.CtArrayTypeReference;
import spoon.reflect.reference.CtIntersectionTypeReference;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.CtInheritanceScanner;
import spoon.reflect.visitor.Filter;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -234,7 +180,24 @@ public <T> void scanCtVariable(CtVariable<T> v) {
substituteAnnotation((CtTypedElement) v);
return;
} else if (child instanceof CtExpression && hasChildEqualsToDefaultValue(v)) {
v.setDefaultExpression((CtExpression<T>) child);

// first trial to detect if part of absolute name of a type is used by a previously recorded element in the model
List<CtElement> allElements = this.jdtTreeBuilder.getFactory().getModel().getElements(new Filter<CtElement>() {
@Override
public boolean matches(CtElement element) {

return (element instanceof CtVariable) && (child.toString().startsWith(((CtNamedElement) element).getSimpleName()));
}
});

CtLiteral simpleExpression = this.jdtTreeBuilder.getFactory().Core().createLiteral();
simpleExpression.setValue(childJDT.toString());

if (allElements.isEmpty()) {
v.setDefaultExpression((CtExpression<T>) child);
} else {
v.setDefaultExpression(simpleExpression);
}
return;
}
super.scanCtVariable(v);
Expand Down
16 changes: 13 additions & 3 deletions src/test/java/spoon/test/api/APITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,18 @@ public SetterMethodWithoutCollectionsFilter(Factory factory) {

@Override
public boolean matches(CtMethod<?> element) {
return isSetterMethod(element) && !isSubTypeOfCollection(element) && super.matches(element);
boolean isSetter = isSetterMethod(element);
boolean isNotSubType = !isSubTypeOfCollection(element);
boolean superMatch = super.matches(element);
return isSetter && isNotSubType && superMatch;
}

private boolean isSubTypeOfCollection(CtMethod<?> element) {
final CtTypeReference<?> type = element.getParameters().get(0).getType();
final List<CtParameter<?>> parameters = element.getParameters();
if (parameters.size() != 1) {
return false;
}
final CtTypeReference<?> type = parameters.get(0).getType();
for (CtTypeReference<?> aCollectionRef : collections) {
if (type.isSubtypeOf(aCollectionRef) || type.equals(aCollectionRef)) {
return true;
Expand All @@ -316,7 +323,10 @@ private boolean isSetterMethod(CtMethod<?> element) {
}
final CtTypeReference<?> typeParameter = parameters.get(0).getType();
final CtTypeReference<CtElement> ctElementRef = element.getFactory().Type().createReference(CtElement.class);
if (!typeParameter.isSubtypeOf(ctElementRef) || !typeParameter.equals(ctElementRef)) {

boolean isSubtypeof = typeParameter.isSubtypeOf(ctElementRef);
boolean isEquals = typeParameter.equals(ctElementRef);
if (!isSubtypeof && !isEquals) {
return false;
}
return element.getSimpleName().startsWith("set") && element.getDeclaringType().getSimpleName().startsWith("Ct") && element.getBody() != null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package spoon.test.variable;

import org.junit.Test;
import spoon.Launcher;
import spoon.reflect.factory.Factory;
import spoon.test.main.MainTest;
import spoon.test.variable.testclasses.Tacos;

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

public class AccessFullyQualifiedFieldTest {
@Test
Expand All @@ -14,4 +16,27 @@ public void testCheckAssignmentContracts() throws Exception {

MainTest.checkAssignmentContracts(factory.Package().getRootPackage());
}
}

@Test
public void testNoFQNWhenShadowedByField() throws Exception {
// contract: no fully qualified name if top package is shadowed by a field variable
Launcher spoon = new Launcher();
spoon.addInputResource("src/test/java/spoon/test/variable/testclasses/BurritosFielded.java");
String output = "target/spooned-" + this.getClass().getSimpleName()+"-Field/";
spoon.setSourceOutputDirectory(output);
spoon.run();
canBeBuilt(output, 7);
}

@Test
public void testNoFQNWhenShadowedByLocalVariable() throws Exception {
// contract: no fully qualified name if top package is shadowed by a local variable
Launcher spoon = new Launcher();
spoon.addInputResource("src/test/java/spoon/test/variable/testclasses/Burritos.java");
String output = "target/spooned-" + this.getClass().getSimpleName()+"-Local/";
spoon.setSourceOutputDirectory(output);
spoon.run();
canBeBuilt(output, 7);
}

}
11 changes: 11 additions & 0 deletions src/test/java/spoon/test/variable/testclasses/Burritos.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package spoon.test.variable.testclasses;


import static spoon.Launcher.SPOONED_CLASSES;

public class Burritos {
void foo() {
Object spoon = null;
Object xx = SPOONED_CLASSES; // cannot be written spoon.o, has to be with implicit visibility or static import
}
}
12 changes: 12 additions & 0 deletions src/test/java/spoon/test/variable/testclasses/BurritosFielded.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package spoon.test.variable.testclasses;


import static spoon.Launcher.SPOONED_CLASSES;

public class BurritosFielded {
Object spoon = null;

void foo() {
Object xx = SPOONED_CLASSES; // cannot be written spoon.o, has to be with implicit visibility or static import
}
}