Skip to content

Commit

Permalink
fix(equal): regenerate EqualVisitor based on new Scanner, which fixes…
Browse files Browse the repository at this point in the history
… a number of bugs incl. INRIA#978
  • Loading branch information
monperrus committed Nov 19, 2016
1 parent 37f4b37 commit 336524d
Show file tree
Hide file tree
Showing 21 changed files with 1,915 additions and 2,391 deletions.
5 changes: 4 additions & 1 deletion src/main/java/spoon/generating/CloneVisitorGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,12 @@ private CtExpression<Object> createBinaryConditions(List<CtMethod<?>> methodsAvo
* Query to get all methods which throw an UnsupportedOperationException. We must avoid to call these methods during a clone process.
*/
private List<CtMethod<?>> getCtMethodThrowUnsupportedOperation(CtMethod<?> method) {
final List<CtMethod<?>> avoid = new ArrayList<>();
final CtInterface<?> ctInterface = getInterfaceOf(method.getDeclaringType());
if (ctInterface == null) {
return avoid;
}
final CtMethod<?> declarationMethod = getMethodByCtMethod(ctInterface, method);
final List<CtMethod<?>> avoid = new ArrayList<>();
for (CtMethod<?> ctMethod : Query.getElements(factory, new OverridingMethodFilter(declarationMethod))) {
if (!avoidThrowUnsupportedOperationException(ctMethod)) {
avoid.add(ctMethod);
Expand Down
98 changes: 49 additions & 49 deletions src/main/java/spoon/generating/CtBiScannerGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
*/
package spoon.generating;

import spoon.processing.AbstractProcessor;
import spoon.processing.AbstractManualProcessor;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtVariableAccess;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypeMember;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtTypeReference;
Expand All @@ -33,69 +34,67 @@

import java.util.List;

public class CtBiScannerGenerator extends AbstractProcessor<CtType<?>> {
public class CtBiScannerGenerator extends AbstractManualProcessor {
private static final String TARGET_BISCANNER_PACKAGE = "spoon.reflect.visitor";
private static final String GENERATING_BISCANNER_PACKAGE = "spoon.generating.scanner";
private static final String GENERATING_BISCANNER = GENERATING_BISCANNER_PACKAGE + ".CtBiScannerTemplate";

@Override
public boolean isToBeProcessed(CtType<?> candidate) {
return CtScanner.class.getName().equals(candidate.getQualifiedName()) && super.isToBeProcessed(candidate);
}
public void process() {

@Override
public void process(CtType<?> element) {
final CtLocalVariable<?> peekElement = getFactory().Class()
.get(GENERATING_BISCANNER_PACKAGE + ".PeekElementTemplate")
.getMethod("statement")
.getBody().getStatement(0);
final CtClass<Object> target = createBiScanner();

new CtScanner() {
@Override
public <T> void visitCtMethod(CtMethod<T> element) {
if (!element.getSimpleName().startsWith("visitCt")) {
return;
for (CtTypeMember tm : getFactory().Class().get(CtScanner.class).getTypeMembers()) {
if (!(tm instanceof CtMethod)) {
continue;
}
CtMethod<?> element = (CtMethod) tm;
if (!element.getSimpleName().startsWith("visitCt")) {
continue;
}

Factory factory = element.getFactory();
CtMethod<?> clone = factory.Core().clone(element);
clone.addComment(getFactory().Code().createComment("autogenerated by " + getClass().getSimpleName(), CtComment.CommentType.INLINE));

// Peek element from Stack.
final CtLocalVariable<?> peek = factory.Core().clone(peekElement);
final CtTypeReference type = factory.Core().clone(clone.getParameters().get(0).getType());
type.getActualTypeArguments().clear();
peek.getDefaultExpression().addTypeCast(type);
peek.setType(type);
clone.getBody().insertBegin(peek);

for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) {
final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0);
if ("getValue".equals(targetInvocation.getExecutable().getSimpleName()) && "CtLiteral".equals(targetInvocation.getExecutable().getDeclaringType().getSimpleName())) {
clone.getBody().getStatement(i--).delete();
continue;
}
CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i));

Factory factory = element.getFactory();
CtMethod<T> clone = factory.Core().clone(element);

// Peek element from Stack.
final CtLocalVariable<?> peek = factory.Core().clone(peekElement);
final CtTypeReference type = factory.Core().clone(clone.getParameters().get(0).getType());
type.getActualTypeArguments().clear();
peek.getDefaultExpression().addTypeCast(type);
peek.setType(type);
clone.getBody().insertBegin(peek);

for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) {
final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0);
if ("getValue".equals(targetInvocation.getExecutable().getSimpleName()) && "CtLiteral".equals(targetInvocation.getExecutable().getDeclaringType().getSimpleName())) {
clone.getBody().getStatement(i--).delete();
continue;
}
CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i));

// Changes to biScan method.
replace.getExecutable().setSimpleName("biScan");

// Creates other inv.
final CtVariableAccess<?> otherRead = factory.Code().createVariableRead(peek.getReference(), false);
replace.addArgument(factory.Code().createInvocation(otherRead, ((CtInvocation) replace.getArguments().get(0)).getExecutable()));

if ("Map".equals(targetInvocation.getExecutable().getType().getSimpleName())) {
((CtExpression) replace.getArguments().get(0)).replace(factory.Code().createInvocation(targetInvocation, factory.Executable().createReference("List Map#values()")));
replace.getArguments().add(1, factory.Code().createInvocation((CtExpression) replace.getArguments().get(1), factory.Executable().createReference("List Map#values()")));
replace.getArguments().remove(2);
}

clone.getBody().getStatement(i).replace(replace);
// Changes to biScan method.
replace.getExecutable().setSimpleName("biScan");

// Creates other inv.
final CtVariableAccess<?> otherRead = factory.Code().createVariableRead(peek.getReference(), false);
replace.addArgument(factory.Code().createInvocation(otherRead, ((CtInvocation) replace.getArguments().get(0)).getExecutable()));

if ("Map".equals(targetInvocation.getExecutable().getType().getSimpleName())) {
((CtExpression) replace.getArguments().get(0)).replace(factory.Code().createInvocation(targetInvocation, factory.Executable().createReference("List Map#values()")));
replace.getArguments().add(1, factory.Code().createInvocation((CtExpression) replace.getArguments().get(1), factory.Executable().createReference("List Map#values()")));
replace.getArguments().remove(2);
}

target.addMethod(clone);
clone.getBody().getStatement(i).replace(replace);
}
}.scan(getFactory().Class().get(CtScanner.class));

target.addMethod(clone);
}

}

private CtClass<Object> createBiScanner() {
Expand All @@ -104,6 +103,7 @@ private CtClass<Object> createBiScanner() {
target.setSimpleName("CtBiScannerDefault");
target.addModifier(ModifierKind.PUBLIC);
aPackage.addType(target);
target.addComment(getFactory().Code().createComment("autogenerated by " + getClass().getSimpleName(), CtComment.CommentType.INLINE));
final List<CtTypeReference> references = target.getReferences(new ReferenceFilter<CtTypeReference>() {
@Override
public boolean matches(CtTypeReference reference) {
Expand Down
96 changes: 0 additions & 96 deletions src/main/java/spoon/generating/EqualsVisitorGenerator.java

This file was deleted.

44 changes: 0 additions & 44 deletions src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java

This file was deleted.

2 changes: 0 additions & 2 deletions src/main/java/spoon/reflect/declaration/CtElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import spoon.reflect.visitor.ReferenceFilter;
import spoon.reflect.visitor.Root;
import spoon.support.DerivedProperty;
import spoon.support.visitor.equals.IgnoredByEquals;

import java.lang.annotation.Annotation;
import java.util.List;
Expand Down Expand Up @@ -265,7 +264,6 @@ <E extends CtElement> List<E> getAnnotatedChildren(
* The list of comments
* @return the list of comment
*/
@IgnoredByEquals
List<CtComment> getComments();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
*/
package spoon.reflect.reference;

import spoon.support.visitor.equals.IgnoredByEquals;

import java.util.List;

/**
Expand All @@ -27,7 +25,6 @@ public interface CtActualTypeContainer {
/**
* Gets the type arguments.
*/
@IgnoredByEquals
List<CtTypeReference<?>> getActualTypeArguments();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import spoon.support.DerivedProperty;

import java.util.List;

/**
* This interface defines a reference to an array.
*/
Expand Down Expand Up @@ -58,4 +60,11 @@ public interface CtArrayTypeReference<T> extends CtTypeReference<T> {

@Override
CtArrayTypeReference<T> clone();

/**
* Gets the type arguments.
*/
@DerivedProperty
List<CtTypeReference<?>> getActualTypeArguments();

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import spoon.reflect.declaration.CtExecutable;
import spoon.support.DerivedProperty;
import spoon.support.visitor.equals.IgnoredByEquals;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -77,10 +76,15 @@ public interface CtExecutableReference<T> extends CtReference, CtActualTypeConta
@DerivedProperty
CtTypeReference<?> getDeclaringType();

/**
* Gets the type arguments.
*/
@DerivedProperty
List<CtTypeReference<?>> getActualTypeArguments();

/**
* Gets the return type of the executable (may be null in noclasspath mode).
*/
@IgnoredByEquals
CtTypeReference<T> getType();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/**
* This abstract bi scanner class declares all scan methods useful for CtBiScannerDefault
*/
public abstract class CtAbstractBiScanner implements CtVisitor {
public abstract class CtAbstractBiScanner extends CtAbstractVisitor {
protected Deque<CtElement> stack = new ArrayDeque<>();

protected void enter(CtElement e) {
Expand Down
Loading

0 comments on commit 336524d

Please sign in to comment.