Skip to content

Commit

Permalink
fix test model change listener
Browse files Browse the repository at this point in the history
  • Loading branch information
tdurieux committed Jun 23, 2017
1 parent 3fae930 commit 98552e1
Showing 1 changed file with 56 additions and 49 deletions.
105 changes: 56 additions & 49 deletions src/test/java/spoon/reflect/ast/AstCheckerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

import org.junit.Test;
import spoon.Launcher;
import spoon.diff.Action;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFieldRead;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtReturn;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtThrow;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtTypeReference;
Expand All @@ -22,8 +18,6 @@
import spoon.support.DerivedProperty;
import spoon.support.UnsettableProperty;
import spoon.support.comparator.CtLineElementComparator;
import spoon.template.TemplateMatcher;
import spoon.template.TemplateParameter;

import java.io.File;
import java.util.Arrays;
Expand Down Expand Up @@ -77,30 +71,36 @@ public void testAvoidSetCollectionSavedOnAST() throws Exception {
final List<CtInvocation<?>> invocations = Query.getElements(factory, new TypeFilter<CtInvocation<?>>(CtInvocation.class) {
@Override
public boolean matches(CtInvocation<?> element) {
if (!element.getExecutable().getSimpleName().startsWith("get")) {
if (!(element.getParent() instanceof CtInvocation)) {
return false;
}
if (!collectionsRef.contains(element.getType())) {
final CtInvocation<?> parent = (CtInvocation<?>) element.getParent();
if (parent.getTarget() == null || !parent.getTarget().equals(element)) {
return false;
}
if (!element.getExecutable().getDeclaringType().getSimpleName().startsWith("Ct")) {
return false;
}
if (!(element.getParent() instanceof CtInvocation)) {
return false;
boolean isDataStructure = false;
for (int i = 0; i < collectionsRef.size(); i++) {
CtTypeReference<?> ctTypeReference = collectionsRef.get(i);
if (element.getType().isSubtypeOf(ctTypeReference)) {
isDataStructure = true;
break;
}
}
final CtInvocation<?> parent = (CtInvocation<?>) element.getParent();
if (!parent.getTarget().equals(element)) {
if (!isDataStructure) {
return false;
}

final String simpleName = parent.getExecutable().getSimpleName();
return simpleName.startsWith("add") || simpleName.startsWith("remove");
return simpleName.startsWith("add") || simpleName.startsWith("remove") || simpleName.startsWith("put");
}
});
if (invocations.size() > 0) {
final String error = invocations.stream() //
.sorted(new CtLineElementComparator()) //
.map(i -> "see " + i.getPosition().getFile().getName() + " at " + i.getPosition().getLine()) //
.map(i -> "see " + i.getPosition().getFile().getAbsoluteFile() + " at " + i.getPosition().getLine()) //
.collect(Collectors.joining(",\n"));
throw new AssertionError(error);
}
Expand All @@ -110,7 +110,6 @@ public boolean matches(CtInvocation<?> element) {
public void testPushToStackChanges() throws Exception {
final Launcher launcher = new Launcher();
launcher.getEnvironment().setNoClasspath(true);
launcher.getEnvironment().setBuildStackChanges(true);
// Implementations.
launcher.addInputResource("./src/main/java/spoon/support/reflect/code");
launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration");
Expand All @@ -120,7 +119,7 @@ public void testPushToStackChanges() throws Exception {
launcher.addInputResource("./src/test/java/spoon/reflect/ast/AstCheckerTest.java");
launcher.buildModel();

final PushStackInIntercessionChecker checker = new PushStackInIntercessionChecker(launcher.getFactory());
final PushStackInIntercessionChecker checker = new PushStackInIntercessionChecker();
checker.scan(launcher.getModel().getRootPackage());
if (!checker.result.isEmpty()) {
System.err.println(checker.count);
Expand All @@ -129,39 +128,21 @@ public void testPushToStackChanges() throws Exception {
}

private class PushStackInIntercessionChecker extends CtScanner {
private final CtInvocation<?> template;
private final List<String> notCandidates;
private String result = "";
private int count;

PushStackInIntercessionChecker(Factory factory) {
final CtType<Object> templateClass = factory.Type().get(Template.class);
template = templateClass.getMethod("templatePush").getBody().getStatement(0);
PushStackInIntercessionChecker() {
notCandidates = Arrays.asList( //
"CtTypeImpl#addTypeMember", //
"CtTypeImpl#removeTypeMember", //
"CtTypeImpl#addFieldAtTop", //
"CtTypeImpl#addField", //
"CtTypeImpl#removeField", //
"CtTypeImpl#addBound", //
"CtTypeImpl#addNestedType", //
"CtTypeImpl#removeNestedType", //
"CtTypeImpl#addMethod", //
"CtTypeImpl#removeMethod", //
"CtBlockImpl#removeStatement", //
"CtAnnotationTypeImpl#addMethod", //
"CtClassImpl#removeConstructor", //
"CtConstructorCallImpl#addArgument", //
"CtInvocationImpl#addArgument", //
"CtTypeParameterReferenceImpl#addBound", //
"CtTypeParameterReferenceImpl#removeBound", //
"CtTypeParameterReferenceImpl#setBounds", //
"CtTypeImpl#setTypeMembers", //
"CtStatementListImpl#setPosition", //
"CtElementImpl#setFactory", //
"CtElementImpl#setPositions", //
"CtElementImpl#setDocComment", //
"CtStatementListImpl#setPosition", //
"CtAnnotationImpl#addValue", //
"CtAnnotationTypeImpl#setFields" //
"CtElementImpl#setParent", //
"CtTypeParameterReferenceImpl#addBound", //
"CtTypeParameterReferenceImpl#removeBound", //
"CtTypeParameterReferenceImpl#setBounds" //
);
}

Expand All @@ -178,19 +159,45 @@ private boolean isToBeProcessed(CtMethod<?> candidate) {
&& (candidate.getSimpleName().startsWith("add") || candidate.getSimpleName().startsWith("set") || candidate.getSimpleName().startsWith("remove")) //
&& candidate.getDeclaringType().getSimpleName().startsWith("Ct") //
&& !isNotCandidate(candidate) //
&& !isSurcharged(candidate) //
&& !isDelegateMethod(candidate) //
&& !isUnsupported(candidate.getBody()) //
&& !hasPushToStackInvocation(candidate.getBody())
&& isSettable(candidate);
&& !hasPushToStackInvocation(candidate.getBody());
}

private boolean isSettable(CtMethod<?> candidate) {
return candidate.getAnnotation(UnsettableProperty.class) == null;
}
private boolean isNotCandidate(CtMethod<?> candidate) {
return "setVisibility".equals(candidate.getSimpleName()) || notCandidates.contains(candidate.getDeclaringType().getSimpleName() + "#" + candidate.getSimpleName());
}

private boolean isSurcharged(CtMethod<?> candidate) {
CtBlock<?> block = candidate.getBody();
if (block.getStatements().size() == 0) {
return false;
}
CtInvocation potentialDelegate;
if (block.getLastStatement() instanceof CtReturn) {
if (!(((CtReturn) block.getLastStatement()).getReturnedExpression() instanceof CtInvocation)) {
if (block.getStatement(0) instanceof CtInvocation) {
potentialDelegate = block.getStatement(0);
} else {
return false;
}
} else {
potentialDelegate = (CtInvocation) ((CtReturn) block.getLastStatement()).getReturnedExpression();
}
} else if (block.getStatement(0) instanceof CtInvocation && block.getStatements().size() == 1) {
potentialDelegate = block.getStatement(0);
} else {
return false;
}
CtExecutable declaration = potentialDelegate.getExecutable().getDeclaration();
if (declaration == null || !(declaration instanceof CtMethod)) {
return false;
}
// check if the invocation has a model change listener
return !isToBeProcessed((CtMethod<?>) declaration);
}

private boolean isDelegateMethod(CtMethod<?> candidate) {
if (candidate.getBody().getStatements().size() == 0) {
return false;
Expand Down Expand Up @@ -227,9 +234,9 @@ private boolean hasPushToStackInvocation(CtBlock<?> body) {
return body.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class) {
@Override
public boolean matches(CtInvocation<?> element) {
return element.getExecutable().getSimpleName().equals(template.getExecutable().getSimpleName()) && super.matches(element);
return "ChangeFactory".equals(element.getExecutable().getDeclaringType().getSimpleName()) && super.matches(element);
}
}).size() == 1;
}).size() > 0;
}

private void process(CtMethod<?> element) {
Expand Down

0 comments on commit 98552e1

Please sign in to comment.