From d312e59a18af55d0dbb2a7cc2dff1d39c96d5575 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Mon, 2 May 2016 16:05:24 +0200 Subject: [PATCH 1/4] feat(equals): Generates equals visitor with CtBiScanner. --- .../generating/CtBiScannerGenerator.java | 72 ++ .../spoon/generating/scanner/CtBiScanner.java | 134 +++ .../scanner/CtBiScannerScanner.java | 89 ++ .../scanner/PeekElementTemplate.java | 28 + .../reference/CtActualTypeContainer.java | 3 + .../reference/CtExecutableReference.java | 2 + .../spoon/reflect/visitor/CtBiScanner.java | 860 ++++++++++++++++++ .../visitor/DefaultJavaPrettyPrinter.java | 5 +- .../compiler/jdt/JDTCommentBuilder.java | 3 + .../support/compiler/jdt/JDTTreeBuilder.java | 4 +- .../reflect/declaration/CtElementImpl.java | 8 +- .../support/visitor/equals/EqualsVisitor.java | 176 ++++ .../visitor/equals/IgnoredByEquals.java | 27 + .../java/JavaReflectionVisitorImpl.java | 2 +- .../spoon/reflect/visitor/CtScannerTest.java | 44 + .../test/fieldaccesses/FieldAccessTest.java | 4 +- src/test/java/spoon/test/main/MainTest.java | 2 +- src/test/java/spoon/test/path/PathTest.java | 1 + 18 files changed, 1451 insertions(+), 13 deletions(-) create mode 100644 src/main/java/spoon/generating/CtBiScannerGenerator.java create mode 100644 src/main/java/spoon/generating/scanner/CtBiScanner.java create mode 100644 src/main/java/spoon/generating/scanner/CtBiScannerScanner.java create mode 100644 src/main/java/spoon/generating/scanner/PeekElementTemplate.java create mode 100644 src/main/java/spoon/reflect/visitor/CtBiScanner.java create mode 100644 src/main/java/spoon/support/visitor/equals/EqualsVisitor.java create mode 100644 src/main/java/spoon/support/visitor/equals/IgnoredByEquals.java diff --git a/src/main/java/spoon/generating/CtBiScannerGenerator.java b/src/main/java/spoon/generating/CtBiScannerGenerator.java new file mode 100644 index 00000000000..cffb6d62328 --- /dev/null +++ b/src/main/java/spoon/generating/CtBiScannerGenerator.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating; + +import spoon.generating.scanner.CtBiScannerScanner; +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtPackage; +import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.CtScanner; +import spoon.reflect.visitor.ReferenceFilter; + +import java.util.List; + +import static spoon.generating.scanner.CtBiScannerScanner.GENERATING_BISCANNER_PACKAGE; +import static spoon.generating.scanner.CtBiScannerScanner.GENERATING_BISCANNER; +import static spoon.generating.scanner.CtBiScannerScanner.TARGET_BISCANNER_PACKAGE; + +public class CtBiScannerGenerator extends AbstractProcessor> { + @Override + public boolean isToBeProcessed(CtType candidate) { + return CtScanner.class.getName().equals(candidate.getQualifiedName()) && super.isToBeProcessed(candidate); + } + + @Override + public void process(CtType element) { + final CtLocalVariable peekElement = getFactory().Class() + .get(GENERATING_BISCANNER_PACKAGE + ".PeekElementTemplate") + .getMethod("statement") + .getBody().getStatement(0); + new CtBiScannerScanner(createBiScanner(), peekElement).scan(getFactory().Class().get(CtScanner.class)); + } + + private CtClass createBiScanner() { + final CtPackage aPackage = getFactory().Package().getOrCreate(TARGET_BISCANNER_PACKAGE); + final CtClass target = getFactory().Class().get(GENERATING_BISCANNER); + target.addModifier(ModifierKind.PUBLIC); + aPackage.addType(target); + final List references = target.getReferences(new ReferenceFilter() { + @Override + public boolean matches(CtTypeReference reference) { + return reference != null && GENERATING_BISCANNER.equals(reference.getQualifiedName()); + } + + @Override + public Class getType() { + return CtTypeReference.class; + } + }); + for (CtTypeReference reference : references) { + reference.setPackage(aPackage.getReference()); + } + return target; + } +} diff --git a/src/main/java/spoon/generating/scanner/CtBiScanner.java b/src/main/java/spoon/generating/scanner/CtBiScanner.java new file mode 100644 index 00000000000..75dae76c004 --- /dev/null +++ b/src/main/java/spoon/generating/scanner/CtBiScanner.java @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating.scanner; + +import spoon.SpoonException; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.visitor.CtVisitor; + +import java.util.Collection; +import java.util.Map; +import java.util.Stack; + +/** + * This visitor implements a deep-search scan on the model for 2 elements. + * + * Ensures that all children nodes are visited once, a visit means three method + * calls, one call to "enter", one call to "exit" and one call to biScan. + * + * Is used by EqualsVisitor. + */ +abstract class CtBiScanner implements CtVisitor { + protected Stack stack = new Stack(); + + protected void enter(CtElement e) { + } + + protected void exit(CtElement e) { + } + + protected boolean isNotEqual = false; + + public boolean biScan(Collection elements, Collection others) { + if (isNotEqual) { + return isNotEqual; + } + if (elements == null) { + if (others != null) { + return fail(); + } + return isNotEqual; + } else if (others == null) { + return fail(); + } + if ((elements.size()) != (others.size())) { + return fail(); + } + for (java.util.Iterator firstIt = elements.iterator(), secondIt = others.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { + biScan(firstIt.next(), secondIt.next()); + } + return isNotEqual; + } + + public boolean biScan(CtElement element, CtElement other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + + stack.push(other); + try { + element.accept(this); + } catch (java.lang.ClassCastException e) { + return fail(); + } finally { + stack.pop(); + } + return isNotEqual; + } + + public boolean biScan(Object element, Object other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + if (element instanceof Map || other instanceof Map) { + throw new SpoonException("Internal error. Can't bi scan Map."); + } + if (element instanceof CtElement) { + if (!(other instanceof CtElement)) { + return fail(); + } + return biScan((CtElement) element, (CtElement) other); + } + if (element instanceof Collection) { + if (!(other instanceof Collection)) { + return fail(); + } + return biScan((Collection) element, (Collection) other); + } + if (!element.equals(other)) { + return fail(); + } + return isNotEqual; + } + + public boolean fail() { + isNotEqual = true; + return true; + } +} diff --git a/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java b/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java new file mode 100644 index 00000000000..af922415713 --- /dev/null +++ b/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java @@ -0,0 +1,89 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating.scanner; + +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtVariableAccess; +import spoon.reflect.declaration.CtAnnotation; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.factory.Factory; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.CtScanner; +import spoon.support.visitor.equals.IgnoredByEquals; + +public class CtBiScannerScanner extends CtScanner { + public static final String TARGET_BISCANNER_PACKAGE = "spoon.reflect.visitor"; + public static final String GENERATING_BISCANNER_PACKAGE = "spoon.generating.scanner"; + public static final String GENERATING_BISCANNER = GENERATING_BISCANNER_PACKAGE + ".CtBiScanner"; + private CtClass target; + private CtLocalVariable peekTemplate; + + public CtBiScannerScanner(CtClass target, CtLocalVariable peekTemplate) { + this.target = target; + this.peekTemplate = peekTemplate; + } + + @Override + public void visitCtMethod(CtMethod element) { + if (!element.getSimpleName().startsWith("visitCt")) { + return; + } + + Factory factory = element.getFactory(); + CtMethod clone = factory.Core().clone(element); + + // Peek element from Stack. + final CtLocalVariable peek = factory.Core().clone(peekTemplate); + 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); + + final CtAnnotation ignoredAnnotation = factory.Core().createAnnotation(); + ignoredAnnotation.setAnnotationType(factory.Type().createReference(IgnoredByEquals.class)); + + for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) { + final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0); + if (targetInvocation.getExecutable().getExecutableDeclaration().getAnnotations().contains(ignoredAnnotation)) { + 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); + } + + target.addMethod(clone); + } +} diff --git a/src/main/java/spoon/generating/scanner/PeekElementTemplate.java b/src/main/java/spoon/generating/scanner/PeekElementTemplate.java new file mode 100644 index 00000000000..aebb25e748d --- /dev/null +++ b/src/main/java/spoon/generating/scanner/PeekElementTemplate.java @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating.scanner; + +import spoon.reflect.declaration.CtElement; + +import java.util.Stack; + +class PeekElementTemplate { + Stack stack; + public void statement() { + CtElement other = stack.peek(); + } +} diff --git a/src/main/java/spoon/reflect/reference/CtActualTypeContainer.java b/src/main/java/spoon/reflect/reference/CtActualTypeContainer.java index e78307973a4..a09788a002a 100644 --- a/src/main/java/spoon/reflect/reference/CtActualTypeContainer.java +++ b/src/main/java/spoon/reflect/reference/CtActualTypeContainer.java @@ -16,6 +16,8 @@ */ package spoon.reflect.reference; +import spoon.support.visitor.equals.IgnoredByEquals; + import java.util.List; /** @@ -25,6 +27,7 @@ public interface CtActualTypeContainer { /** * Gets the type arguments. */ + @IgnoredByEquals List> getActualTypeArguments(); /** diff --git a/src/main/java/spoon/reflect/reference/CtExecutableReference.java b/src/main/java/spoon/reflect/reference/CtExecutableReference.java index 9dd3bda0cf4..8cdb1041cd9 100644 --- a/src/main/java/spoon/reflect/reference/CtExecutableReference.java +++ b/src/main/java/spoon/reflect/reference/CtExecutableReference.java @@ -17,6 +17,7 @@ package spoon.reflect.reference; import spoon.reflect.declaration.CtExecutable; +import spoon.support.visitor.equals.IgnoredByEquals; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -75,6 +76,7 @@ public interface CtExecutableReference extends CtReference, CtGenericElementR /** * Gets the return type of the executable (may be null in noclasspath mode). */ + @IgnoredByEquals CtTypeReference getType(); /** diff --git a/src/main/java/spoon/reflect/visitor/CtBiScanner.java b/src/main/java/spoon/reflect/visitor/CtBiScanner.java new file mode 100644 index 00000000000..3acf6648170 --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/CtBiScanner.java @@ -0,0 +1,860 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + +package spoon.reflect.visitor; + + +/** + * This visitor implements a deep-search scan on the model for 2 elements. + * + * Ensures that all children nodes are visited once, a visit means three method + * calls, one call to "enter", one call to "exit" and one call to biScan. + * + * Is used by EqualsVisitor. + */ +public abstract class CtBiScanner implements spoon.reflect.visitor.CtVisitor { + protected java.util.Stack stack = new java.util.Stack(); + + protected void enter(spoon.reflect.declaration.CtElement e) { + } + + protected void exit(spoon.reflect.declaration.CtElement e) { + } + + protected boolean isNotEqual = false; + + public boolean biScan(java.util.Collection elements, java.util.Collection others) { + if (isNotEqual) { + return isNotEqual; + } + if (elements == null) { + if (others != null) { + return fail(); + } + return isNotEqual; + } else if (others == null) { + return fail(); + } + if ((elements.size()) != (others.size())) { + return fail(); + } + for (java.util.Iterator firstIt = elements.iterator(), secondIt = others.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { + biScan(firstIt.next(), secondIt.next()); + } + return isNotEqual; + } + + public boolean biScan(spoon.reflect.declaration.CtElement element, spoon.reflect.declaration.CtElement other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + stack.push(other); + try { + element.accept(spoon.reflect.visitor.CtBiScanner.this); + } catch (java.lang.ClassCastException e) { + return fail(); + } finally { + stack.pop(); + } + return isNotEqual; + } + + public boolean biScan(java.lang.Object element, java.lang.Object other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + if ((element instanceof java.util.Map) || (other instanceof java.util.Map)) { + throw new spoon.SpoonException("Internal error. Can't bi scan Map."); + } + if (element instanceof spoon.reflect.declaration.CtElement) { + if (!(other instanceof spoon.reflect.declaration.CtElement)) { + return fail(); + } + return biScan(((spoon.reflect.declaration.CtElement) (element)), ((spoon.reflect.declaration.CtElement) (other))); + } + if (element instanceof java.util.Collection) { + if (!(other instanceof java.util.Collection)) { + return fail(); + } + return biScan(((java.util.Collection) (element)), ((java.util.Collection) (other))); + } + if (!(element.equals(other))) { + return fail(); + } + return isNotEqual; + } + + public boolean fail() { + isNotEqual = true; + return true; + } + + public void visitCtAnnotation(final spoon.reflect.declaration.CtAnnotation annotation) { + spoon.reflect.declaration.CtAnnotation other = ((spoon.reflect.declaration.CtAnnotation) (stack.peek())); + enter(annotation); + biScan(annotation.getAnnotationType(), other.getAnnotationType()); + biScan(annotation.getAnnotations(), other.getAnnotations()); + biScan(annotation.getValues().values(), other.getValues().values()); + exit(annotation); + } + + public void visitCtAnnotationType(final spoon.reflect.declaration.CtAnnotationType annotationType) { + spoon.reflect.declaration.CtAnnotationType other = ((spoon.reflect.declaration.CtAnnotationType) (stack.peek())); + enter(annotationType); + biScan(annotationType.getAnnotations(), other.getAnnotations()); + biScan(annotationType.getNestedTypes(), other.getNestedTypes()); + biScan(annotationType.getFields(), other.getFields()); + biScan(annotationType.getComments(), other.getComments()); + exit(annotationType); + } + + public void visitCtAnonymousExecutable(final spoon.reflect.declaration.CtAnonymousExecutable anonymousExec) { + spoon.reflect.declaration.CtAnonymousExecutable other = ((spoon.reflect.declaration.CtAnonymousExecutable) (stack.peek())); + enter(anonymousExec); + biScan(anonymousExec.getAnnotations(), other.getAnnotations()); + biScan(anonymousExec.getBody(), other.getBody()); + biScan(anonymousExec.getComments(), other.getComments()); + exit(anonymousExec); + } + + public > void visitCtArrayAccess(final spoon.reflect.code.CtArrayAccess arrayAccess) { + spoon.reflect.code.CtArrayAccess other = ((spoon.reflect.code.CtArrayAccess) (stack.peek())); + enter(arrayAccess); + biScan(arrayAccess.getAnnotations(), other.getAnnotations()); + biScan(arrayAccess.getType(), other.getType()); + biScan(arrayAccess.getTypeCasts(), other.getTypeCasts()); + biScan(arrayAccess.getTarget(), other.getTarget()); + biScan(arrayAccess.getIndexExpression(), other.getIndexExpression()); + biScan(arrayAccess.getComments(), other.getComments()); + exit(arrayAccess); + } + + @java.lang.Override + public void visitCtArrayRead(final spoon.reflect.code.CtArrayRead arrayRead) { + spoon.reflect.code.CtArrayRead other = ((spoon.reflect.code.CtArrayRead) (stack.peek())); + enter(arrayRead); + biScan(arrayRead.getAnnotations(), other.getAnnotations()); + biScan(arrayRead.getType(), other.getType()); + biScan(arrayRead.getTypeCasts(), other.getTypeCasts()); + biScan(arrayRead.getTarget(), other.getTarget()); + biScan(arrayRead.getIndexExpression(), other.getIndexExpression()); + biScan(arrayRead.getComments(), other.getComments()); + exit(arrayRead); + } + + @java.lang.Override + public void visitCtArrayWrite(final spoon.reflect.code.CtArrayWrite arrayWrite) { + spoon.reflect.code.CtArrayWrite other = ((spoon.reflect.code.CtArrayWrite) (stack.peek())); + enter(arrayWrite); + biScan(arrayWrite.getAnnotations(), other.getAnnotations()); + biScan(arrayWrite.getType(), other.getType()); + biScan(arrayWrite.getTypeCasts(), other.getTypeCasts()); + biScan(arrayWrite.getTarget(), other.getTarget()); + biScan(arrayWrite.getIndexExpression(), other.getIndexExpression()); + biScan(arrayWrite.getComments(), other.getComments()); + exit(arrayWrite); + } + + public void visitCtArrayTypeReference(final spoon.reflect.reference.CtArrayTypeReference reference) { + spoon.reflect.reference.CtArrayTypeReference other = ((spoon.reflect.reference.CtArrayTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getPackage(), other.getPackage()); + biScan(reference.getComponentType(), other.getComponentType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtAssert(final spoon.reflect.code.CtAssert asserted) { + spoon.reflect.code.CtAssert other = ((spoon.reflect.code.CtAssert) (stack.peek())); + enter(asserted); + biScan(asserted.getAnnotations(), other.getAnnotations()); + biScan(asserted.getAssertExpression(), other.getAssertExpression()); + biScan(asserted.getExpression(), other.getExpression()); + biScan(asserted.getComments(), other.getComments()); + exit(asserted); + } + + public void visitCtAssignment(final spoon.reflect.code.CtAssignment assignement) { + spoon.reflect.code.CtAssignment other = ((spoon.reflect.code.CtAssignment) (stack.peek())); + enter(assignement); + biScan(assignement.getAnnotations(), other.getAnnotations()); + biScan(assignement.getType(), other.getType()); + biScan(assignement.getTypeCasts(), other.getTypeCasts()); + biScan(assignement.getAssigned(), other.getAssigned()); + biScan(assignement.getAssignment(), other.getAssignment()); + biScan(assignement.getComments(), other.getComments()); + exit(assignement); + } + + public void visitCtBinaryOperator(final spoon.reflect.code.CtBinaryOperator operator) { + spoon.reflect.code.CtBinaryOperator other = ((spoon.reflect.code.CtBinaryOperator) (stack.peek())); + enter(operator); + biScan(operator.getAnnotations(), other.getAnnotations()); + biScan(operator.getType(), other.getType()); + biScan(operator.getTypeCasts(), other.getTypeCasts()); + biScan(operator.getLeftHandOperand(), other.getLeftHandOperand()); + biScan(operator.getRightHandOperand(), other.getRightHandOperand()); + biScan(operator.getComments(), other.getComments()); + exit(operator); + } + + public void visitCtBlock(final spoon.reflect.code.CtBlock block) { + spoon.reflect.code.CtBlock other = ((spoon.reflect.code.CtBlock) (stack.peek())); + enter(block); + biScan(block.getAnnotations(), other.getAnnotations()); + biScan(block.getStatements(), other.getStatements()); + biScan(block.getComments(), other.getComments()); + exit(block); + } + + public void visitCtBreak(final spoon.reflect.code.CtBreak breakStatement) { + spoon.reflect.code.CtBreak other = ((spoon.reflect.code.CtBreak) (stack.peek())); + enter(breakStatement); + biScan(breakStatement.getAnnotations(), other.getAnnotations()); + biScan(breakStatement.getComments(), other.getComments()); + exit(breakStatement); + } + + public void visitCtCase(final spoon.reflect.code.CtCase caseStatement) { + spoon.reflect.code.CtCase other = ((spoon.reflect.code.CtCase) (stack.peek())); + enter(caseStatement); + biScan(caseStatement.getAnnotations(), other.getAnnotations()); + biScan(caseStatement.getCaseExpression(), other.getCaseExpression()); + biScan(caseStatement.getStatements(), other.getStatements()); + biScan(caseStatement.getComments(), other.getComments()); + exit(caseStatement); + } + + public void visitCtCatch(final spoon.reflect.code.CtCatch catchBlock) { + spoon.reflect.code.CtCatch other = ((spoon.reflect.code.CtCatch) (stack.peek())); + enter(catchBlock); + biScan(catchBlock.getAnnotations(), other.getAnnotations()); + biScan(catchBlock.getParameter(), other.getParameter()); + biScan(catchBlock.getBody(), other.getBody()); + biScan(catchBlock.getComments(), other.getComments()); + exit(catchBlock); + } + + public void visitCtClass(final spoon.reflect.declaration.CtClass ctClass) { + spoon.reflect.declaration.CtClass other = ((spoon.reflect.declaration.CtClass) (stack.peek())); + enter(ctClass); + biScan(ctClass.getAnnotations(), other.getAnnotations()); + biScan(ctClass.getSuperclass(), other.getSuperclass()); + biScan(ctClass.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(ctClass.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(ctClass.getAnonymousExecutables(), other.getAnonymousExecutables()); + biScan(ctClass.getNestedTypes(), other.getNestedTypes()); + biScan(ctClass.getFields(), other.getFields()); + biScan(ctClass.getConstructors(), other.getConstructors()); + biScan(ctClass.getMethods(), other.getMethods()); + biScan(ctClass.getComments(), other.getComments()); + exit(ctClass); + } + + public void visitCtConditional(final spoon.reflect.code.CtConditional conditional) { + spoon.reflect.code.CtConditional other = ((spoon.reflect.code.CtConditional) (stack.peek())); + enter(conditional); + biScan(conditional.getAnnotations(), other.getAnnotations()); + biScan(conditional.getCondition(), other.getCondition()); + biScan(conditional.getThenExpression(), other.getThenExpression()); + biScan(conditional.getElseExpression(), other.getElseExpression()); + biScan(conditional.getComments(), other.getComments()); + exit(conditional); + } + + public void visitCtConstructor(final spoon.reflect.declaration.CtConstructor c) { + spoon.reflect.declaration.CtConstructor other = ((spoon.reflect.declaration.CtConstructor) (stack.peek())); + enter(c); + biScan(c.getAnnotations(), other.getAnnotations()); + biScan(c.getParameters(), other.getParameters()); + biScan(c.getThrownTypes(), other.getThrownTypes()); + biScan(c.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(c.getBody(), other.getBody()); + biScan(c.getComments(), other.getComments()); + exit(c); + } + + public void visitCtContinue(final spoon.reflect.code.CtContinue continueStatement) { + spoon.reflect.code.CtContinue other = ((spoon.reflect.code.CtContinue) (stack.peek())); + enter(continueStatement); + biScan(continueStatement.getAnnotations(), other.getAnnotations()); + biScan(continueStatement.getLabelledStatement(), other.getLabelledStatement()); + biScan(continueStatement.getComments(), other.getComments()); + exit(continueStatement); + } + + public void visitCtDo(final spoon.reflect.code.CtDo doLoop) { + spoon.reflect.code.CtDo other = ((spoon.reflect.code.CtDo) (stack.peek())); + enter(doLoop); + biScan(doLoop.getAnnotations(), other.getAnnotations()); + biScan(doLoop.getLoopingExpression(), other.getLoopingExpression()); + biScan(doLoop.getBody(), other.getBody()); + biScan(doLoop.getComments(), other.getComments()); + exit(doLoop); + } + + public > void visitCtEnum(final spoon.reflect.declaration.CtEnum ctEnum) { + spoon.reflect.declaration.CtEnum other = ((spoon.reflect.declaration.CtEnum) (stack.peek())); + enter(ctEnum); + biScan(ctEnum.getAnnotations(), other.getAnnotations()); + biScan(ctEnum.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(ctEnum.getFields(), other.getFields()); + biScan(ctEnum.getConstructors(), other.getConstructors()); + biScan(ctEnum.getMethods(), other.getMethods()); + biScan(ctEnum.getNestedTypes(), other.getNestedTypes()); + biScan(ctEnum.getComments(), other.getComments()); + exit(ctEnum); + } + + public void visitCtExecutableReference(final spoon.reflect.reference.CtExecutableReference reference) { + spoon.reflect.reference.CtExecutableReference other = ((spoon.reflect.reference.CtExecutableReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getParameters(), other.getParameters()); + biScan(reference.getAnnotations(), other.getAnnotations()); + biScan(reference.getComments(), other.getComments()); + exit(reference); + } + + public void visitCtField(final spoon.reflect.declaration.CtField f) { + spoon.reflect.declaration.CtField other = ((spoon.reflect.declaration.CtField) (stack.peek())); + enter(f); + biScan(f.getAnnotations(), other.getAnnotations()); + biScan(f.getType(), other.getType()); + biScan(f.getDefaultExpression(), other.getDefaultExpression()); + biScan(f.getComments(), other.getComments()); + exit(f); + } + + @java.lang.Override + public void visitCtEnumValue(final spoon.reflect.declaration.CtEnumValue enumValue) { + spoon.reflect.declaration.CtEnumValue other = ((spoon.reflect.declaration.CtEnumValue) (stack.peek())); + enter(enumValue); + biScan(enumValue.getAnnotations(), other.getAnnotations()); + biScan(enumValue.getType(), other.getType()); + biScan(enumValue.getDefaultExpression(), other.getDefaultExpression()); + biScan(enumValue.getComments(), other.getComments()); + exit(enumValue); + } + + @java.lang.Override + public void visitCtThisAccess(final spoon.reflect.code.CtThisAccess thisAccess) { + spoon.reflect.code.CtThisAccess other = ((spoon.reflect.code.CtThisAccess) (stack.peek())); + enter(thisAccess); + biScan(thisAccess.getType(), other.getType()); + biScan(thisAccess.getTypeCasts(), other.getTypeCasts()); + biScan(thisAccess.getTarget(), other.getTarget()); + biScan(thisAccess.getComments(), other.getComments()); + exit(thisAccess); + } + + public void visitCtAnnotationFieldAccess(final spoon.reflect.code.CtAnnotationFieldAccess annotationFieldAccess) { + spoon.reflect.code.CtAnnotationFieldAccess other = ((spoon.reflect.code.CtAnnotationFieldAccess) (stack.peek())); + enter(annotationFieldAccess); + biScan(annotationFieldAccess.getAnnotations(), other.getAnnotations()); + biScan(annotationFieldAccess.getType(), other.getType()); + biScan(annotationFieldAccess.getTypeCasts(), other.getTypeCasts()); + biScan(annotationFieldAccess.getTarget(), other.getTarget()); + biScan(annotationFieldAccess.getVariable(), other.getVariable()); + biScan(annotationFieldAccess.getComments(), other.getComments()); + exit(annotationFieldAccess); + } + + public void visitCtFieldReference(final spoon.reflect.reference.CtFieldReference reference) { + spoon.reflect.reference.CtFieldReference other = ((spoon.reflect.reference.CtFieldReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtFor(final spoon.reflect.code.CtFor forLoop) { + spoon.reflect.code.CtFor other = ((spoon.reflect.code.CtFor) (stack.peek())); + enter(forLoop); + biScan(forLoop.getAnnotations(), other.getAnnotations()); + biScan(forLoop.getForInit(), other.getForInit()); + biScan(forLoop.getExpression(), other.getExpression()); + biScan(forLoop.getForUpdate(), other.getForUpdate()); + biScan(forLoop.getBody(), other.getBody()); + biScan(forLoop.getComments(), other.getComments()); + exit(forLoop); + } + + public void visitCtForEach(final spoon.reflect.code.CtForEach foreach) { + spoon.reflect.code.CtForEach other = ((spoon.reflect.code.CtForEach) (stack.peek())); + enter(foreach); + biScan(foreach.getAnnotations(), other.getAnnotations()); + biScan(foreach.getVariable(), other.getVariable()); + biScan(foreach.getExpression(), other.getExpression()); + biScan(foreach.getBody(), other.getBody()); + biScan(foreach.getComments(), other.getComments()); + exit(foreach); + } + + public void visitCtIf(final spoon.reflect.code.CtIf ifElement) { + spoon.reflect.code.CtIf other = ((spoon.reflect.code.CtIf) (stack.peek())); + enter(ifElement); + biScan(ifElement.getAnnotations(), other.getAnnotations()); + biScan(ifElement.getCondition(), other.getCondition()); + biScan(((spoon.reflect.code.CtStatement) (ifElement.getThenStatement())), other.getThenStatement()); + biScan(((spoon.reflect.code.CtStatement) (ifElement.getElseStatement())), other.getElseStatement()); + biScan(ifElement.getComments(), other.getComments()); + exit(ifElement); + } + + public void visitCtInterface(final spoon.reflect.declaration.CtInterface intrface) { + spoon.reflect.declaration.CtInterface other = ((spoon.reflect.declaration.CtInterface) (stack.peek())); + enter(intrface); + biScan(intrface.getAnnotations(), other.getAnnotations()); + biScan(intrface.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(intrface.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(intrface.getNestedTypes(), other.getNestedTypes()); + biScan(intrface.getFields(), other.getFields()); + biScan(intrface.getMethods(), other.getMethods()); + biScan(intrface.getComments(), other.getComments()); + exit(intrface); + } + + public void visitCtInvocation(final spoon.reflect.code.CtInvocation invocation) { + spoon.reflect.code.CtInvocation other = ((spoon.reflect.code.CtInvocation) (stack.peek())); + enter(invocation); + biScan(invocation.getAnnotations(), other.getAnnotations()); + biScan(invocation.getTypeCasts(), other.getTypeCasts()); + biScan(invocation.getTarget(), other.getTarget()); + biScan(invocation.getExecutable(), other.getExecutable()); + biScan(invocation.getArguments(), other.getArguments()); + biScan(invocation.getComments(), other.getComments()); + exit(invocation); + } + + public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { + spoon.reflect.code.CtLiteral other = ((spoon.reflect.code.CtLiteral) (stack.peek())); + enter(literal); + biScan(literal.getAnnotations(), other.getAnnotations()); + biScan(literal.getType(), other.getType()); + biScan(literal.getValue(), other.getValue()); + biScan(literal.getTypeCasts(), other.getTypeCasts()); + biScan(literal.getComments(), other.getComments()); + exit(literal); + } + + public void visitCtLocalVariable(final spoon.reflect.code.CtLocalVariable localVariable) { + spoon.reflect.code.CtLocalVariable other = ((spoon.reflect.code.CtLocalVariable) (stack.peek())); + enter(localVariable); + biScan(localVariable.getAnnotations(), other.getAnnotations()); + biScan(localVariable.getType(), other.getType()); + biScan(localVariable.getDefaultExpression(), other.getDefaultExpression()); + biScan(localVariable.getComments(), other.getComments()); + exit(localVariable); + } + + public void visitCtLocalVariableReference(final spoon.reflect.reference.CtLocalVariableReference reference) { + spoon.reflect.reference.CtLocalVariableReference other = ((spoon.reflect.reference.CtLocalVariableReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtCatchVariable(final spoon.reflect.code.CtCatchVariable catchVariable) { + spoon.reflect.code.CtCatchVariable other = ((spoon.reflect.code.CtCatchVariable) (stack.peek())); + enter(catchVariable); + biScan(catchVariable.getAnnotations(), other.getAnnotations()); + biScan(catchVariable.getType(), other.getType()); + biScan(catchVariable.getComments(), other.getComments()); + exit(catchVariable); + } + + public void visitCtCatchVariableReference(final spoon.reflect.reference.CtCatchVariableReference reference) { + spoon.reflect.reference.CtCatchVariableReference other = ((spoon.reflect.reference.CtCatchVariableReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtMethod(final spoon.reflect.declaration.CtMethod m) { + spoon.reflect.declaration.CtMethod other = ((spoon.reflect.declaration.CtMethod) (stack.peek())); + enter(m); + biScan(m.getAnnotations(), other.getAnnotations()); + biScan(m.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(m.getType(), other.getType()); + biScan(m.getParameters(), other.getParameters()); + biScan(m.getThrownTypes(), other.getThrownTypes()); + biScan(m.getBody(), other.getBody()); + biScan(m.getComments(), other.getComments()); + exit(m); + } + + public void visitCtNewArray(final spoon.reflect.code.CtNewArray newArray) { + spoon.reflect.code.CtNewArray other = ((spoon.reflect.code.CtNewArray) (stack.peek())); + enter(newArray); + biScan(newArray.getAnnotations(), other.getAnnotations()); + biScan(newArray.getType(), other.getType()); + biScan(newArray.getTypeCasts(), other.getTypeCasts()); + biScan(newArray.getElements(), other.getElements()); + biScan(newArray.getDimensionExpressions(), other.getDimensionExpressions()); + biScan(newArray.getComments(), other.getComments()); + exit(newArray); + } + + @java.lang.Override + public void visitCtConstructorCall(final spoon.reflect.code.CtConstructorCall ctConstructorCall) { + spoon.reflect.code.CtConstructorCall other = ((spoon.reflect.code.CtConstructorCall) (stack.peek())); + enter(ctConstructorCall); + biScan(ctConstructorCall.getAnnotations(), other.getAnnotations()); + biScan(ctConstructorCall.getTypeCasts(), other.getTypeCasts()); + biScan(ctConstructorCall.getExecutable(), other.getExecutable()); + biScan(ctConstructorCall.getTarget(), other.getTarget()); + biScan(ctConstructorCall.getArguments(), other.getArguments()); + biScan(ctConstructorCall.getComments(), other.getComments()); + exit(ctConstructorCall); + } + + public void visitCtNewClass(final spoon.reflect.code.CtNewClass newClass) { + spoon.reflect.code.CtNewClass other = ((spoon.reflect.code.CtNewClass) (stack.peek())); + enter(newClass); + biScan(newClass.getAnnotations(), other.getAnnotations()); + biScan(newClass.getTypeCasts(), other.getTypeCasts()); + biScan(newClass.getExecutable(), other.getExecutable()); + biScan(newClass.getTarget(), other.getTarget()); + biScan(newClass.getArguments(), other.getArguments()); + biScan(newClass.getAnonymousClass(), other.getAnonymousClass()); + biScan(newClass.getComments(), other.getComments()); + exit(newClass); + } + + @java.lang.Override + public void visitCtLambda(final spoon.reflect.code.CtLambda lambda) { + spoon.reflect.code.CtLambda other = ((spoon.reflect.code.CtLambda) (stack.peek())); + enter(lambda); + biScan(lambda.getAnnotations(), other.getAnnotations()); + biScan(lambda.getType(), other.getType()); + biScan(lambda.getTypeCasts(), other.getTypeCasts()); + biScan(lambda.getParameters(), other.getParameters()); + biScan(lambda.getBody(), other.getBody()); + biScan(lambda.getExpression(), other.getExpression()); + biScan(lambda.getComments(), other.getComments()); + exit(lambda); + } + + @java.lang.Override + public > void visitCtExecutableReferenceExpression(final spoon.reflect.code.CtExecutableReferenceExpression expression) { + spoon.reflect.code.CtExecutableReferenceExpression other = ((spoon.reflect.code.CtExecutableReferenceExpression) (stack.peek())); + enter(expression); + biScan(expression.getType(), other.getType()); + biScan(expression.getTypeCasts(), other.getTypeCasts()); + biScan(expression.getExecutable(), other.getExecutable()); + biScan(expression.getTarget(), other.getTarget()); + exit(expression); + } + + public void visitCtOperatorAssignment(final spoon.reflect.code.CtOperatorAssignment assignment) { + spoon.reflect.code.CtOperatorAssignment other = ((spoon.reflect.code.CtOperatorAssignment) (stack.peek())); + enter(assignment); + biScan(assignment.getAnnotations(), other.getAnnotations()); + biScan(assignment.getType(), other.getType()); + biScan(assignment.getTypeCasts(), other.getTypeCasts()); + biScan(assignment.getAssigned(), other.getAssigned()); + biScan(assignment.getAssignment(), other.getAssignment()); + biScan(assignment.getComments(), other.getComments()); + exit(assignment); + } + + public void visitCtPackage(final spoon.reflect.declaration.CtPackage ctPackage) { + spoon.reflect.declaration.CtPackage other = ((spoon.reflect.declaration.CtPackage) (stack.peek())); + enter(ctPackage); + biScan(ctPackage.getAnnotations(), other.getAnnotations()); + biScan(ctPackage.getPackages(), other.getPackages()); + biScan(ctPackage.getTypes(), other.getTypes()); + biScan(ctPackage.getComments(), other.getComments()); + exit(ctPackage); + } + + public void visitCtPackageReference(final spoon.reflect.reference.CtPackageReference reference) { + spoon.reflect.reference.CtPackageReference other = ((spoon.reflect.reference.CtPackageReference) (stack.peek())); + enter(reference); + exit(reference); + } + + public void visitCtParameter(final spoon.reflect.declaration.CtParameter parameter) { + spoon.reflect.declaration.CtParameter other = ((spoon.reflect.declaration.CtParameter) (stack.peek())); + enter(parameter); + biScan(parameter.getAnnotations(), other.getAnnotations()); + biScan(parameter.getType(), other.getType()); + biScan(parameter.getComments(), other.getComments()); + exit(parameter); + } + + public void visitCtParameterReference(final spoon.reflect.reference.CtParameterReference reference) { + spoon.reflect.reference.CtParameterReference other = ((spoon.reflect.reference.CtParameterReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtReturn(final spoon.reflect.code.CtReturn returnStatement) { + spoon.reflect.code.CtReturn other = ((spoon.reflect.code.CtReturn) (stack.peek())); + enter(returnStatement); + biScan(returnStatement.getAnnotations(), other.getAnnotations()); + biScan(returnStatement.getReturnedExpression(), other.getReturnedExpression()); + biScan(returnStatement.getComments(), other.getComments()); + exit(returnStatement); + } + + public void visitCtStatementList(final spoon.reflect.code.CtStatementList statements) { + spoon.reflect.code.CtStatementList other = ((spoon.reflect.code.CtStatementList) (stack.peek())); + enter(statements); + biScan(statements.getAnnotations(), other.getAnnotations()); + biScan(statements.getStatements(), other.getStatements()); + biScan(statements.getComments(), other.getComments()); + exit(statements); + } + + public void visitCtSwitch(final spoon.reflect.code.CtSwitch switchStatement) { + spoon.reflect.code.CtSwitch other = ((spoon.reflect.code.CtSwitch) (stack.peek())); + enter(switchStatement); + biScan(switchStatement.getAnnotations(), other.getAnnotations()); + biScan(switchStatement.getSelector(), other.getSelector()); + biScan(switchStatement.getCases(), other.getCases()); + biScan(switchStatement.getComments(), other.getComments()); + exit(switchStatement); + } + + public void visitCtSynchronized(final spoon.reflect.code.CtSynchronized synchro) { + spoon.reflect.code.CtSynchronized other = ((spoon.reflect.code.CtSynchronized) (stack.peek())); + enter(synchro); + biScan(synchro.getAnnotations(), other.getAnnotations()); + biScan(synchro.getExpression(), other.getExpression()); + biScan(synchro.getBlock(), other.getBlock()); + biScan(synchro.getComments(), other.getComments()); + exit(synchro); + } + + public void visitCtThrow(final spoon.reflect.code.CtThrow throwStatement) { + spoon.reflect.code.CtThrow other = ((spoon.reflect.code.CtThrow) (stack.peek())); + enter(throwStatement); + biScan(throwStatement.getAnnotations(), other.getAnnotations()); + biScan(throwStatement.getThrownExpression(), other.getThrownExpression()); + biScan(throwStatement.getComments(), other.getComments()); + exit(throwStatement); + } + + public void visitCtTry(final spoon.reflect.code.CtTry tryBlock) { + spoon.reflect.code.CtTry other = ((spoon.reflect.code.CtTry) (stack.peek())); + enter(tryBlock); + biScan(tryBlock.getAnnotations(), other.getAnnotations()); + biScan(tryBlock.getBody(), other.getBody()); + biScan(tryBlock.getCatchers(), other.getCatchers()); + biScan(tryBlock.getFinalizer(), other.getFinalizer()); + biScan(tryBlock.getComments(), other.getComments()); + exit(tryBlock); + } + + @java.lang.Override + public void visitCtTryWithResource(final spoon.reflect.code.CtTryWithResource tryWithResource) { + spoon.reflect.code.CtTryWithResource other = ((spoon.reflect.code.CtTryWithResource) (stack.peek())); + enter(tryWithResource); + biScan(tryWithResource.getAnnotations(), other.getAnnotations()); + biScan(tryWithResource.getResources(), other.getResources()); + biScan(tryWithResource.getBody(), other.getBody()); + biScan(tryWithResource.getCatchers(), other.getCatchers()); + biScan(tryWithResource.getFinalizer(), other.getFinalizer()); + biScan(tryWithResource.getComments(), other.getComments()); + exit(tryWithResource); + } + + public void visitCtTypeParameterReference(final spoon.reflect.reference.CtTypeParameterReference ref) { + spoon.reflect.reference.CtTypeParameterReference other = ((spoon.reflect.reference.CtTypeParameterReference) (stack.peek())); + enter(ref); + biScan(ref.getPackage(), other.getPackage()); + biScan(ref.getDeclaringType(), other.getDeclaringType()); + biScan(ref.getAnnotations(), other.getAnnotations()); + biScan(ref.getBoundingType(), other.getBoundingType()); + exit(ref); + } + + @java.lang.Override + public void visitCtIntersectionTypeReference(final spoon.reflect.reference.CtIntersectionTypeReference reference) { + spoon.reflect.reference.CtIntersectionTypeReference other = ((spoon.reflect.reference.CtIntersectionTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getBounds(), other.getBounds()); + exit(reference); + } + + public void visitCtTypeReference(final spoon.reflect.reference.CtTypeReference reference) { + spoon.reflect.reference.CtTypeReference other = ((spoon.reflect.reference.CtTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getPackage(), other.getPackage()); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + biScan(reference.getComments(), other.getComments()); + exit(reference); + } + + @java.lang.Override + public void visitCtCircularTypeReference(final spoon.reflect.internal.CtCircularTypeReference reference) { + spoon.reflect.internal.CtCircularTypeReference other = ((spoon.reflect.internal.CtCircularTypeReference) (stack.peek())); + enter(reference); + exit(reference); + } + + @java.lang.Override + public void visitCtTypeAccess(final spoon.reflect.code.CtTypeAccess typeAccess) { + spoon.reflect.code.CtTypeAccess other = ((spoon.reflect.code.CtTypeAccess) (stack.peek())); + enter(typeAccess); + biScan(typeAccess.getAnnotations(), other.getAnnotations()); + biScan(typeAccess.getType(), other.getType()); + biScan(typeAccess.getTypeCasts(), other.getTypeCasts()); + biScan(typeAccess.getAccessedType(), other.getAccessedType()); + biScan(typeAccess.getComments(), other.getComments()); + exit(typeAccess); + } + + public void visitCtUnaryOperator(final spoon.reflect.code.CtUnaryOperator operator) { + spoon.reflect.code.CtUnaryOperator other = ((spoon.reflect.code.CtUnaryOperator) (stack.peek())); + enter(operator); + biScan(operator.getAnnotations(), other.getAnnotations()); + biScan(operator.getType(), other.getType()); + biScan(operator.getTypeCasts(), other.getTypeCasts()); + biScan(operator.getOperand(), other.getOperand()); + biScan(operator.getComments(), other.getComments()); + exit(operator); + } + + @java.lang.Override + public void visitCtVariableRead(final spoon.reflect.code.CtVariableRead variableRead) { + spoon.reflect.code.CtVariableRead other = ((spoon.reflect.code.CtVariableRead) (stack.peek())); + enter(variableRead); + biScan(variableRead.getAnnotations(), other.getAnnotations()); + biScan(variableRead.getType(), other.getType()); + biScan(variableRead.getTypeCasts(), other.getTypeCasts()); + biScan(variableRead.getVariable(), other.getVariable()); + biScan(variableRead.getComments(), other.getComments()); + exit(variableRead); + } + + @java.lang.Override + public void visitCtVariableWrite(final spoon.reflect.code.CtVariableWrite variableWrite) { + spoon.reflect.code.CtVariableWrite other = ((spoon.reflect.code.CtVariableWrite) (stack.peek())); + enter(variableWrite); + biScan(variableWrite.getAnnotations(), other.getAnnotations()); + biScan(variableWrite.getType(), other.getType()); + biScan(variableWrite.getTypeCasts(), other.getTypeCasts()); + biScan(variableWrite.getVariable(), other.getVariable()); + biScan(variableWrite.getComments(), other.getComments()); + exit(variableWrite); + } + + public void visitCtWhile(final spoon.reflect.code.CtWhile whileLoop) { + spoon.reflect.code.CtWhile other = ((spoon.reflect.code.CtWhile) (stack.peek())); + enter(whileLoop); + biScan(whileLoop.getAnnotations(), other.getAnnotations()); + biScan(whileLoop.getLoopingExpression(), other.getLoopingExpression()); + biScan(whileLoop.getBody(), other.getBody()); + biScan(whileLoop.getComments(), other.getComments()); + exit(whileLoop); + } + + public void visitCtCodeSnippetExpression(final spoon.reflect.code.CtCodeSnippetExpression expression) { + spoon.reflect.code.CtCodeSnippetExpression other = ((spoon.reflect.code.CtCodeSnippetExpression) (stack.peek())); + enter(expression); + exit(expression); + } + + public void visitCtCodeSnippetStatement(final spoon.reflect.code.CtCodeSnippetStatement statement) { + spoon.reflect.code.CtCodeSnippetStatement other = ((spoon.reflect.code.CtCodeSnippetStatement) (stack.peek())); + enter(statement); + exit(statement); + } + + public void visitCtUnboundVariableReference(final spoon.reflect.reference.CtUnboundVariableReference reference) { + spoon.reflect.reference.CtUnboundVariableReference other = ((spoon.reflect.reference.CtUnboundVariableReference) (stack.peek())); + enter(reference); + exit(reference); + } + + @java.lang.Override + public void visitCtFieldRead(final spoon.reflect.code.CtFieldRead fieldRead) { + spoon.reflect.code.CtFieldRead other = ((spoon.reflect.code.CtFieldRead) (stack.peek())); + enter(fieldRead); + biScan(fieldRead.getAnnotations(), other.getAnnotations()); + biScan(fieldRead.getTypeCasts(), other.getTypeCasts()); + biScan(fieldRead.getTarget(), other.getTarget()); + biScan(fieldRead.getVariable(), other.getVariable()); + biScan(fieldRead.getComments(), other.getComments()); + exit(fieldRead); + } + + @java.lang.Override + public void visitCtFieldWrite(final spoon.reflect.code.CtFieldWrite fieldWrite) { + spoon.reflect.code.CtFieldWrite other = ((spoon.reflect.code.CtFieldWrite) (stack.peek())); + enter(fieldWrite); + biScan(fieldWrite.getAnnotations(), other.getAnnotations()); + biScan(fieldWrite.getTypeCasts(), other.getTypeCasts()); + biScan(fieldWrite.getTarget(), other.getTarget()); + biScan(fieldWrite.getVariable(), other.getVariable()); + biScan(fieldWrite.getComments(), other.getComments()); + exit(fieldWrite); + } + + @java.lang.Override + public void visitCtSuperAccess(final spoon.reflect.code.CtSuperAccess f) { + spoon.reflect.code.CtSuperAccess other = ((spoon.reflect.code.CtSuperAccess) (stack.peek())); + enter(f); + biScan(f.getAnnotations(), other.getAnnotations()); + biScan(f.getType(), other.getType()); + biScan(f.getTypeCasts(), other.getTypeCasts()); + biScan(f.getTarget(), other.getTarget()); + biScan(f.getComments(), other.getComments()); + exit(f); + } + + @java.lang.Override + public void visitCtComment(final spoon.reflect.code.CtComment comment) { + spoon.reflect.code.CtComment other = ((spoon.reflect.code.CtComment) (stack.peek())); + enter(comment); + exit(comment); + } +} + diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index 685827ba524..851f464d5d4 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -1235,7 +1235,10 @@ public void visitCtFor(CtFor forLoop) { } write("; "); scan(forLoop.getExpression()); - write("; "); + write(";"); + if (!forLoop.getForUpdate().isEmpty()) { + write(" "); + } for (CtStatement s : forLoop.getForUpdate()) { scan(s); write(" , "); diff --git a/src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java index 6c933fbad87..2af19f308b6 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java @@ -390,6 +390,9 @@ public void scan(CtElement element) { if (element == null) { return; } + if (element.isImplicit()) { + return; + } CtElement body; try { Method getBody = element.getClass().getMethod("getBody"); diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 1291b8d9f7b..c307589cd0e 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -627,9 +627,9 @@ public CtExecutableReference getExecutableReference(MethodBinding exec) { return null; } - final CtExecutableReference ref = factory.Core().createExecutableReference(); + final CtExecutableReference ref = factory.Core().createExecutableReference(); ref.setSimpleName(new String(exec.selector)); - ref.setType((CtTypeReference) getTypeReference(exec.returnType)); + ref.setType(getTypeReference(exec.returnType)); if (exec instanceof ProblemMethodBinding) { if (exec.declaringClass != null && Arrays.asList(exec.declaringClass.methods()).contains(exec)) { diff --git a/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java b/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java index 54d2c7c42bc..339a0f45698 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java @@ -39,6 +39,7 @@ import spoon.support.visitor.HashcodeVisitor; import spoon.support.visitor.SignaturePrinter; import spoon.support.visitor.TypeReferenceScanner; +import spoon.support.visitor.equals.EqualsVisitor; import spoon.support.visitor.replace.ReplacementVisitor; import java.io.Serializable; @@ -141,12 +142,7 @@ public boolean equals(Object o) { if (this == o) { return true; } - boolean ret = false; - if ((o instanceof CtElement)) { - String current = getDeepRepresentation(this); - String other = getDeepRepresentation((CtElement) o); - ret = current.equals(other); - } + boolean ret = EqualsVisitor.equals(this, (CtElement) o); // neat online testing of core Java contract if (ret && this.hashCode() != o.hashCode()) { throw new IllegalStateException("violation of equal/hashcode contract between \n" + getDeepRepresentation(this) + "\nand\n" + getDeepRepresentation((CtElement) o) + "\n"); diff --git a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java new file mode 100644 index 00000000000..6ba7b31fd34 --- /dev/null +++ b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java @@ -0,0 +1,176 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.visitor.equals; + +import spoon.reflect.code.CtBinaryOperator; +import spoon.reflect.code.CtBreak; +import spoon.reflect.code.CtContinue; +import spoon.reflect.code.CtOperatorAssignment; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtUnaryOperator; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.CtNamedElement; +import spoon.reflect.declaration.CtParameter; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtReference; +import spoon.reflect.visitor.CtBiScanner; + +public class EqualsVisitor extends CtBiScanner { + public static boolean equals(CtElement element, CtElement other) { + return !new EqualsVisitor().biScan(element, other); + } + + @Override + public boolean biScan(CtElement element, CtElement other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + + try { + String leftName = ((CtNamedElement) element).getSimpleName(); + String rightName = ((CtNamedElement) other).getSimpleName(); + if (!leftName.equals(rightName)) { + return fail(); + } + } catch (ClassCastException ignored) { + } + try { + String leftName = ((CtReference) element).getSimpleName(); + String rightName = ((CtReference) other).getSimpleName(); + if (!leftName.equals(rightName)) { + return fail(); + } + } catch (ClassCastException ignored) { + } + try { + String leftLabel = ((CtStatement) element).getLabel(); + String rightLabel = ((CtStatement) other).getLabel(); + if (leftLabel == null && rightLabel == null) { + return super.biScan(element, other); + } + if (leftLabel == null || !leftLabel.equals(rightLabel)) { + return fail(); + } + } catch (ClassCastException ignored) { + } + + return super.biScan(element, other); + } + + @Override + public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { + final CtOperatorAssignment peek = (CtOperatorAssignment) this.stack.peek(); + if (!assignment.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtOperatorAssignment(assignment); + } + + @Override + public void visitCtBinaryOperator(CtBinaryOperator e) { + final CtBinaryOperator peek = (CtBinaryOperator) this.stack.peek(); + if (!e.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtBinaryOperator(e); + } + + @Override + public void visitCtUnaryOperator(CtUnaryOperator e) { + final CtUnaryOperator peek = (CtUnaryOperator) this.stack.peek(); + if (!e.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtUnaryOperator(e); + } + + @Override + public void visitCtArrayTypeReference(CtArrayTypeReference e) { + final CtArrayTypeReference peek = (CtArrayTypeReference) this.stack.peek(); + if (e.getDimensionCount() != peek.getDimensionCount()) { + isNotEqual = true; + return; + } + super.visitCtArrayTypeReference(e); + } + + @Override + public void visitCtBreak(CtBreak e) { + final CtBreak peek = (CtBreak) this.stack.peek(); + if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + isNotEqual = true; + return; + } + super.visitCtBreak(e); + } + + @Override + public void visitCtContinue(CtContinue e) { + final CtContinue peek = (CtContinue) this.stack.peek(); + if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + isNotEqual = true; + return; + } + super.visitCtContinue(e); + } + + @Override + public void visitCtExecutableReference(CtExecutableReference e) { + final CtExecutableReference peek = (CtExecutableReference) this.stack.peek(); + if (e.isConstructor() != peek.isConstructor()) { + isNotEqual = true; + return; + } + super.visitCtExecutableReference(e); + } + + @Override + public void visitCtMethod(CtMethod e) { + final CtMethod peek = (CtMethod) this.stack.peek(); + if (e.isDefaultMethod() != peek.isDefaultMethod()) { + isNotEqual = true; + return; + } + super.visitCtMethod(e); + } + + @Override + public void visitCtParameter(CtParameter e) { + final CtParameter peek = (CtParameter) this.stack.peek(); + if (e.isVarArgs() != peek.isVarArgs()) { + isNotEqual = true; + return; + } + super.visitCtParameter(e); + } +} diff --git a/src/main/java/spoon/support/visitor/equals/IgnoredByEquals.java b/src/main/java/spoon/support/visitor/equals/IgnoredByEquals.java new file mode 100644 index 00000000000..2879616941b --- /dev/null +++ b/src/main/java/spoon/support/visitor/equals/IgnoredByEquals.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.visitor.equals; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface IgnoredByEquals { +} diff --git a/src/main/java/spoon/support/visitor/java/JavaReflectionVisitorImpl.java b/src/main/java/spoon/support/visitor/java/JavaReflectionVisitorImpl.java index b7d82f64042..92e6bff7461 100644 --- a/src/main/java/spoon/support/visitor/java/JavaReflectionVisitorImpl.java +++ b/src/main/java/spoon/support/visitor/java/JavaReflectionVisitorImpl.java @@ -296,7 +296,7 @@ public void visitArrayReference(Class typeArray) { @Override public void visitClassReference(Class clazz) { - if (clazz.getPackage() != null) { + if (clazz.getPackage() != null && clazz.getEnclosingClass() == null) { visitPackage(clazz.getPackage()); } if (clazz.getEnclosingClass() != null) { diff --git a/src/test/java/spoon/reflect/visitor/CtScannerTest.java b/src/test/java/spoon/reflect/visitor/CtScannerTest.java index f16cfe1a430..dcff251827f 100644 --- a/src/test/java/spoon/reflect/visitor/CtScannerTest.java +++ b/src/test/java/spoon/reflect/visitor/CtScannerTest.java @@ -19,6 +19,7 @@ import org.junit.Test; import spoon.Launcher; +import spoon.generating.CtBiScannerGenerator; import spoon.generating.ReplacementVisitorGenerator; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; @@ -96,4 +97,47 @@ public Class getType() { assertThat(build(new File("./src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java")).Class().get(ReplacementVisitor.class)) .isEqualTo(build(new File("./target/generated/spoon/support/visitor/replace/ReplacementVisitor.java")).Class().get(ReplacementVisitor.class)); } + + @Test + public void testGenerateCtBiScanner() throws Exception { + class RegexFilter implements Filter> { + private final Pattern regex; + + private RegexFilter(String regex) { + if (regex == null) { + throw new IllegalArgumentException(); + } + this.regex = Pattern.compile(regex); + } + + public boolean matches(CtType element) { + Matcher m = regex.matcher(element.getQualifiedName()); + return m.matches(); + } + + public Class getType() { + return CtElement.class; + } + } + + final Launcher launcher = new Launcher(); + launcher.getEnvironment().setNoClasspath(true); + launcher.getEnvironment().setGenerateJavadoc(true); + launcher.getEnvironment().useTabulations(true); + launcher.setSourceOutputDirectory("./target/generated/"); + // interfaces. + launcher.addInputResource("./src/main/java/spoon/reflect/code"); + launcher.addInputResource("./src/main/java/spoon/reflect/declaration"); + launcher.addInputResource("./src/main/java/spoon/reflect/reference"); + launcher.addInputResource("./src/main/java/spoon/reflect/internal"); + // Utils. + launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtScanner.java"); + launcher.addInputResource("./src/main/java/spoon/generating/scanner/"); + launcher.addProcessor(new CtBiScannerGenerator()); + launcher.setOutputFilter(new RegexFilter("spoon.reflect.visitor.CtBiScanner")); + launcher.run(); + + assertThat(build(new File("./src/main/java/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)) + .isEqualTo(build(new File("./target/generated/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)); + } } diff --git a/src/test/java/spoon/test/fieldaccesses/FieldAccessTest.java b/src/test/java/spoon/test/fieldaccesses/FieldAccessTest.java index 26268388e05..57d1f9ca76b 100644 --- a/src/test/java/spoon/test/fieldaccesses/FieldAccessTest.java +++ b/src/test/java/spoon/test/fieldaccesses/FieldAccessTest.java @@ -27,7 +27,6 @@ import spoon.test.fieldaccesses.testclasses.Panini; import spoon.test.fieldaccesses.testclasses.Pozole; import spoon.test.fieldaccesses.testclasses.Tacos; -import spoon.testing.Assert; import spoon.testing.utils.ModelUtils; import java.util.List; @@ -37,7 +36,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static spoon.testing.Assert.*; +import static spoon.testing.Assert.assertThat; import static spoon.testing.utils.ModelUtils.build; import static spoon.testing.utils.ModelUtils.buildClass; @@ -234,6 +233,7 @@ public void testIncrementationOnAVarIsAUnaryOperator() throws Exception { final List> unaryOperators = make.getElements(new TypeFilter>(CtUnaryOperator.class)); final CtFieldRead fieldRead = aMole.getFactory().Core().createFieldRead(); + fieldRead.setTarget(aMole.getFactory().Code().createThisAccess(aMole.getReference())); final CtFieldReference fieldReference = aMole.getField("i").getReference(); fieldRead.setVariable(fieldReference); diff --git a/src/test/java/spoon/test/main/MainTest.java b/src/test/java/spoon/test/main/MainTest.java index 69c5ac53c2d..5af1dab48ee 100644 --- a/src/test/java/spoon/test/main/MainTest.java +++ b/src/test/java/spoon/test/main/MainTest.java @@ -120,7 +120,7 @@ public void visitCtExecutableReference(CtExecutableReference reference) { assertNotNull(executableDeclaration); assertEquals(reference.getSimpleName(), executableDeclaration.getSimpleName()); - // when a generic type is used in a parameter, the shadow type doesn't have these information. + // when a generic type is used in a parameter and return type, the shadow type doesn't have these information. boolean hasGeneric = false; for (int i = 0; i < reference.getParameters().size(); i++) { if (reference.getParameters().get(i) instanceof CtTypeParameterReference) { diff --git a/src/test/java/spoon/test/path/PathTest.java b/src/test/java/spoon/test/path/PathTest.java index 625d765bc70..a3383aea76c 100644 --- a/src/test/java/spoon/test/path/PathTest.java +++ b/src/test/java/spoon/test/path/PathTest.java @@ -86,6 +86,7 @@ public void testPathFromString() throws Exception { CtLiteral literal = factory.Core().createLiteral(); literal.setValue("salut"); + literal.setType(literal.getFactory().Type().STRING); equals(new CtPathStringBuilder().fromString(".spoon.test.path.Foo.toto#defaultValue"), literal); } From 68b6ee448b6d1b6200fd568fb457cedae910de6a Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Tue, 24 May 2016 15:08:35 +0200 Subject: [PATCH 2/4] feat(equals): Dissociate CtBiScanner and EqualsVisitor. --- .../generating/EqualsVisitorGenerator.java | 60 ++ .../generating/equals/EqualsVisitor.java | 44 + .../equals/EqualsVisitorScanner.java | 61 ++ .../scanner/CtBiScannerScanner.java | 9 - .../spoon/reflect/declaration/CtElement.java | 2 + .../spoon/reflect/visitor/CtBiScanner.java | 5 + .../equals/EqualsCheckerInheritance.java | 181 ++++ .../support/visitor/equals/EqualsVisitor.java | 814 +++++++++++++++--- .../spoon/reflect/visitor/CtScannerTest.java | 85 +- 9 files changed, 1077 insertions(+), 184 deletions(-) create mode 100644 src/main/java/spoon/generating/EqualsVisitorGenerator.java create mode 100644 src/main/java/spoon/generating/equals/EqualsVisitor.java create mode 100644 src/main/java/spoon/generating/equals/EqualsVisitorScanner.java create mode 100644 src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java diff --git a/src/main/java/spoon/generating/EqualsVisitorGenerator.java b/src/main/java/spoon/generating/EqualsVisitorGenerator.java new file mode 100644 index 00000000000..c3995a1b2c9 --- /dev/null +++ b/src/main/java/spoon/generating/EqualsVisitorGenerator.java @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating; + +import spoon.generating.equals.EqualsVisitorScanner; +import spoon.processing.AbstractManualProcessor; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtPackage; +import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.CtBiScanner; +import spoon.reflect.visitor.ReferenceFilter; + +import java.util.List; + +import static spoon.generating.equals.EqualsVisitorScanner.GENERATING_EQUALS; +import static spoon.generating.equals.EqualsVisitorScanner.TARGET_EQUALS_PACKAGE; + +public class EqualsVisitorGenerator extends AbstractManualProcessor { + @Override + public void process() { + new EqualsVisitorScanner(createEqualsVisitor()).scan(getFactory().Class().get(CtBiScanner.class)); + } + + private CtClass createEqualsVisitor() { + final CtPackage aPackage = getFactory().Package().getOrCreate(TARGET_EQUALS_PACKAGE); + final CtClass target = getFactory().Class().get(GENERATING_EQUALS); + target.addModifier(ModifierKind.PUBLIC); + aPackage.addType(target); + final List references = target.getReferences(new ReferenceFilter() { + @Override + public boolean matches(CtTypeReference reference) { + return reference != null && GENERATING_EQUALS.equals(reference.getQualifiedName()); + } + + @Override + public Class getType() { + return CtTypeReference.class; + } + }); + for (CtTypeReference reference : references) { + reference.setPackage(aPackage.getReference()); + } + return target; + } +} diff --git a/src/main/java/spoon/generating/equals/EqualsVisitor.java b/src/main/java/spoon/generating/equals/EqualsVisitor.java new file mode 100644 index 00000000000..6f011721bc8 --- /dev/null +++ b/src/main/java/spoon/generating/equals/EqualsVisitor.java @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating.equals; + +import spoon.reflect.declaration.CtElement; +import spoon.reflect.visitor.CtBiScanner; +import spoon.support.visitor.equals.EqualsCheckerInheritance; + +/** + * Used to check equality between an element and another one. + * + * This class is generated automatically by the processor {@link spoon.generating.EqualsVisitorGenerator}. + */ +class EqualsVisitor extends CtBiScanner { + public static boolean equals(CtElement element, CtElement other) { + return !new EqualsVisitor().biScan(element, other); + } + + private final EqualsCheckerInheritance checker = new EqualsCheckerInheritance(); + + @Override + protected void enter(CtElement e) { + super.enter(e); + checker.setOther(stack.peek()); + checker.scan(e); + if (checker.isNotEqual()) { + fail(); + } + } +} diff --git a/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java b/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java new file mode 100644 index 00000000000..8efc8b6a384 --- /dev/null +++ b/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.generating.equals; + +import spoon.reflect.code.CtInvocation; +import spoon.reflect.declaration.CtAnnotation; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.factory.Factory; +import spoon.reflect.visitor.CtScanner; +import spoon.support.visitor.equals.IgnoredByEquals; + +public class EqualsVisitorScanner extends CtScanner { + public static final String TARGET_EQUALS_PACKAGE = "spoon.support.visitor.equals"; + public static final String GENERATING_EQUALS_PACKAGE = "spoon.generating.equals"; + public static final String GENERATING_EQUALS = GENERATING_EQUALS_PACKAGE + ".EqualsVisitor"; + private CtClass target; + + public EqualsVisitorScanner(CtClass target) { + this.target = target; + } + + @Override + public void visitCtMethod(CtMethod element) { + if (!element.getSimpleName().startsWith("visitCt")) { + return; + } + + Factory factory = element.getFactory(); + CtMethod clone = factory.Core().clone(element); + + final CtAnnotation ignoredAnnotation = factory.Core().createAnnotation(); + ignoredAnnotation.setAnnotationType(factory.Type().createReference(IgnoredByEquals.class)); + + for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) { + final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0); + if (targetInvocation.getExecutable().getExecutableDeclaration().getAnnotations().contains(ignoredAnnotation)) { + clone.getBody().getStatement(i--).delete(); + continue; + } + CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i)); + clone.getBody().getStatement(i).replace(replace); + } + + target.addMethod(clone); + } +} diff --git a/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java b/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java index af922415713..44a24f2facd 100644 --- a/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java +++ b/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java @@ -20,13 +20,11 @@ import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtVariableAccess; -import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.CtScanner; -import spoon.support.visitor.equals.IgnoredByEquals; public class CtBiScannerScanner extends CtScanner { public static final String TARGET_BISCANNER_PACKAGE = "spoon.reflect.visitor"; @@ -57,15 +55,8 @@ public void visitCtMethod(CtMethod element) { peek.setType(type); clone.getBody().insertBegin(peek); - final CtAnnotation ignoredAnnotation = factory.Core().createAnnotation(); - ignoredAnnotation.setAnnotationType(factory.Type().createReference(IgnoredByEquals.class)); - for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) { final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0); - if (targetInvocation.getExecutable().getExecutableDeclaration().getAnnotations().contains(ignoredAnnotation)) { - clone.getBody().getStatement(i--).delete(); - continue; - } CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i)); // Changes to biScan method. diff --git a/src/main/java/spoon/reflect/declaration/CtElement.java b/src/main/java/spoon/reflect/declaration/CtElement.java index 12124ce7c69..1e6098badd0 100644 --- a/src/main/java/spoon/reflect/declaration/CtElement.java +++ b/src/main/java/spoon/reflect/declaration/CtElement.java @@ -25,6 +25,7 @@ import spoon.reflect.visitor.Filter; import spoon.reflect.visitor.ReferenceFilter; import spoon.reflect.visitor.Root; +import spoon.support.visitor.equals.IgnoredByEquals; import java.lang.annotation.Annotation; import java.util.List; @@ -266,6 +267,7 @@ List getAnnotatedChildren( * The list of comments * @return the list of comment */ + @IgnoredByEquals List getComments(); /** diff --git a/src/main/java/spoon/reflect/visitor/CtBiScanner.java b/src/main/java/spoon/reflect/visitor/CtBiScanner.java index 3acf6648170..f0e2763f736 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScanner.java @@ -198,6 +198,7 @@ public void visitCtArrayTypeReference(final spoon.reflect.reference.CtArrayT biScan(reference.getDeclaringType(), other.getDeclaringType()); biScan(reference.getPackage(), other.getPackage()); biScan(reference.getComponentType(), other.getComponentType()); + biScan(reference.getActualTypeArguments(), other.getActualTypeArguments()); biScan(reference.getAnnotations(), other.getAnnotations()); exit(reference); } @@ -348,7 +349,9 @@ public void visitCtExecutableReference(final spoon.reflect.reference.CtExecu spoon.reflect.reference.CtExecutableReference other = ((spoon.reflect.reference.CtExecutableReference) (stack.peek())); enter(reference); biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getType(), other.getType()); biScan(reference.getParameters(), other.getParameters()); + biScan(reference.getActualTypeArguments(), other.getActualTypeArguments()); biScan(reference.getAnnotations(), other.getAnnotations()); biScan(reference.getComments(), other.getComments()); exit(reference); @@ -709,6 +712,7 @@ public void visitCtTypeParameterReference(final spoon.reflect.reference.CtTypePa enter(ref); biScan(ref.getPackage(), other.getPackage()); biScan(ref.getDeclaringType(), other.getDeclaringType()); + biScan(ref.getActualTypeArguments(), other.getActualTypeArguments()); biScan(ref.getAnnotations(), other.getAnnotations()); biScan(ref.getBoundingType(), other.getBoundingType()); exit(ref); @@ -727,6 +731,7 @@ public void visitCtTypeReference(final spoon.reflect.reference.CtTypeReferen enter(reference); biScan(reference.getPackage(), other.getPackage()); biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getActualTypeArguments(), other.getActualTypeArguments()); biScan(reference.getAnnotations(), other.getAnnotations()); biScan(reference.getComments(), other.getComments()); exit(reference); diff --git a/src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java b/src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java new file mode 100644 index 00000000000..9c42d3aa881 --- /dev/null +++ b/src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.visitor.equals; + +import spoon.reflect.code.CtBinaryOperator; +import spoon.reflect.code.CtBreak; +import spoon.reflect.code.CtContinue; +import spoon.reflect.code.CtOperatorAssignment; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtUnaryOperator; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.CtModifiable; +import spoon.reflect.declaration.CtNamedElement; +import spoon.reflect.declaration.CtParameter; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtReference; +import spoon.reflect.visitor.CtInheritanceScanner; + +public class EqualsCheckerInheritance extends CtInheritanceScanner { + private CtElement other; + private boolean isNotEqual; + + public void setOther(CtElement other) { + this.other = other; + } + + public boolean isNotEqual() { + return isNotEqual; + } + + @Override + public void scanCtNamedElement(CtNamedElement e) { + final CtNamedElement peek = (CtNamedElement) this.other; + if (!e.getSimpleName().equals(peek.getSimpleName())) { + isNotEqual = true; + return; + } + super.scanCtNamedElement(e); + } + + @Override + public void scanCtReference(CtReference reference) { + final CtReference peek = (CtReference) this.other; + if (!reference.getSimpleName().equals(peek.getSimpleName())) { + isNotEqual = true; + return; + } + super.scanCtReference(reference); + } + + @Override + public void scanCtStatement(CtStatement s) { + final CtStatement peek = (CtStatement) this.other; + final String leftLabel = s.getLabel(); + final String rightLabel = peek.getLabel(); + if (leftLabel == null && rightLabel == null) { + super.scanCtStatement(s); + return; + } + if (leftLabel == null || !leftLabel.equals(rightLabel)) { + isNotEqual = true; + return; + } + super.scanCtStatement(s); + } + + @Override + public void scanCtModifiable(CtModifiable m) { + final CtModifiable peek = (CtModifiable) this.other; +/* + biScan(m.getVisibility(), other.getVisibility()); + biScan(m.getModifiers(), other.getModifiers()); +*/ + } + + @Override + public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { + final CtOperatorAssignment peek = (CtOperatorAssignment) this.other; + if (!assignment.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtOperatorAssignment(assignment); + } + + @Override + public void visitCtBinaryOperator(CtBinaryOperator e) { + final CtBinaryOperator peek = (CtBinaryOperator) this.other; + if (!e.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtBinaryOperator(e); + } + + @Override + public void visitCtUnaryOperator(CtUnaryOperator e) { + final CtUnaryOperator peek = (CtUnaryOperator) this.other; + if (!e.getKind().equals(peek.getKind())) { + isNotEqual = true; + return; + } + super.visitCtUnaryOperator(e); + } + + @Override + public void visitCtArrayTypeReference(CtArrayTypeReference e) { + final CtArrayTypeReference peek = (CtArrayTypeReference) this.other; + if (e.getDimensionCount() != peek.getDimensionCount()) { + isNotEqual = true; + return; + } + super.visitCtArrayTypeReference(e); + } + + @Override + public void visitCtBreak(CtBreak e) { + final CtBreak peek = (CtBreak) this.other; + if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + isNotEqual = true; + return; + } + super.visitCtBreak(e); + } + + @Override + public void visitCtContinue(CtContinue e) { + final CtContinue peek = (CtContinue) this.other; + if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + isNotEqual = true; + return; + } + super.visitCtContinue(e); + } + + @Override + public void visitCtExecutableReference(CtExecutableReference e) { + final CtExecutableReference peek = (CtExecutableReference) this.other; + if (e.isConstructor() != peek.isConstructor()) { + isNotEqual = true; + return; + } + super.visitCtExecutableReference(e); + } + + @Override + public void visitCtMethod(CtMethod e) { + final CtMethod peek = (CtMethod) this.other; + if (e.isDefaultMethod() != peek.isDefaultMethod()) { + isNotEqual = true; + return; + } + super.visitCtMethod(e); + } + + @Override + public void visitCtParameter(CtParameter e) { + final CtParameter peek = (CtParameter) this.other; + if (e.isVarArgs() != peek.isVarArgs()) { + isNotEqual = true; + return; + } + super.visitCtParameter(e); + } +} diff --git a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java index 6ba7b31fd34..22dd7674320 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java @@ -14,163 +14,707 @@ * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ + + package spoon.support.visitor.equals; -import spoon.reflect.code.CtBinaryOperator; -import spoon.reflect.code.CtBreak; -import spoon.reflect.code.CtContinue; -import spoon.reflect.code.CtOperatorAssignment; -import spoon.reflect.code.CtStatement; -import spoon.reflect.code.CtUnaryOperator; -import spoon.reflect.declaration.CtElement; -import spoon.reflect.declaration.CtMethod; -import spoon.reflect.declaration.CtNamedElement; -import spoon.reflect.declaration.CtParameter; -import spoon.reflect.reference.CtArrayTypeReference; -import spoon.reflect.reference.CtExecutableReference; -import spoon.reflect.reference.CtReference; -import spoon.reflect.visitor.CtBiScanner; - -public class EqualsVisitor extends CtBiScanner { - public static boolean equals(CtElement element, CtElement other) { - return !new EqualsVisitor().biScan(element, other); - } - - @Override - public boolean biScan(CtElement element, CtElement other) { - if (isNotEqual) { - return isNotEqual; - } - if (element == null) { - if (other != null) { - return fail(); - } - return isNotEqual; - } else if (other == null) { - return fail(); - } - if (element == other) { - return isNotEqual; - } - try { - String leftName = ((CtNamedElement) element).getSimpleName(); - String rightName = ((CtNamedElement) other).getSimpleName(); - if (!leftName.equals(rightName)) { - return fail(); - } - } catch (ClassCastException ignored) { - } - try { - String leftName = ((CtReference) element).getSimpleName(); - String rightName = ((CtReference) other).getSimpleName(); - if (!leftName.equals(rightName)) { - return fail(); - } - } catch (ClassCastException ignored) { - } - try { - String leftLabel = ((CtStatement) element).getLabel(); - String rightLabel = ((CtStatement) other).getLabel(); - if (leftLabel == null && rightLabel == null) { - return super.biScan(element, other); - } - if (leftLabel == null || !leftLabel.equals(rightLabel)) { - return fail(); - } - } catch (ClassCastException ignored) { +/** + * Used to check equality between an element and another one. + * + * This class is generated automatically by the processor {@link spoon.generating.EqualsVisitorGenerator}. + */ +public class EqualsVisitor extends spoon.reflect.visitor.CtBiScanner { + public static boolean equals(spoon.reflect.declaration.CtElement element, spoon.reflect.declaration.CtElement other) { + return !(new spoon.support.visitor.equals.EqualsVisitor().biScan(element, other)); + } + + private final spoon.support.visitor.equals.EqualsCheckerInheritance checker = new spoon.support.visitor.equals.EqualsCheckerInheritance(); + + @java.lang.Override + protected void enter(spoon.reflect.declaration.CtElement e) { + super.enter(e); + checker.setOther(stack.peek()); + checker.scan(e); + if (checker.isNotEqual()) { + fail(); } + } - return super.biScan(element, other); + public void visitCtAnnotation(final spoon.reflect.declaration.CtAnnotation annotation) { + spoon.reflect.declaration.CtAnnotation other = ((spoon.reflect.declaration.CtAnnotation) (stack.peek())); + enter(annotation); + biScan(annotation.getAnnotationType(), other.getAnnotationType()); + biScan(annotation.getAnnotations(), other.getAnnotations()); + biScan(annotation.getValues().values(), other.getValues().values()); + exit(annotation); } - @Override - public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { - final CtOperatorAssignment peek = (CtOperatorAssignment) this.stack.peek(); - if (!assignment.getKind().equals(peek.getKind())) { - isNotEqual = true; - return; - } - super.visitCtOperatorAssignment(assignment); + public void visitCtAnnotationType(final spoon.reflect.declaration.CtAnnotationType annotationType) { + spoon.reflect.declaration.CtAnnotationType other = ((spoon.reflect.declaration.CtAnnotationType) (stack.peek())); + enter(annotationType); + biScan(annotationType.getAnnotations(), other.getAnnotations()); + biScan(annotationType.getNestedTypes(), other.getNestedTypes()); + biScan(annotationType.getFields(), other.getFields()); + exit(annotationType); } - @Override - public void visitCtBinaryOperator(CtBinaryOperator e) { - final CtBinaryOperator peek = (CtBinaryOperator) this.stack.peek(); - if (!e.getKind().equals(peek.getKind())) { - isNotEqual = true; - return; - } - super.visitCtBinaryOperator(e); + public void visitCtAnonymousExecutable(final spoon.reflect.declaration.CtAnonymousExecutable anonymousExec) { + spoon.reflect.declaration.CtAnonymousExecutable other = ((spoon.reflect.declaration.CtAnonymousExecutable) (stack.peek())); + enter(anonymousExec); + biScan(anonymousExec.getAnnotations(), other.getAnnotations()); + biScan(anonymousExec.getBody(), other.getBody()); + exit(anonymousExec); } - @Override - public void visitCtUnaryOperator(CtUnaryOperator e) { - final CtUnaryOperator peek = (CtUnaryOperator) this.stack.peek(); - if (!e.getKind().equals(peek.getKind())) { - isNotEqual = true; - return; - } - super.visitCtUnaryOperator(e); + public > void visitCtArrayAccess(final spoon.reflect.code.CtArrayAccess arrayAccess) { + spoon.reflect.code.CtArrayAccess other = ((spoon.reflect.code.CtArrayAccess) (stack.peek())); + enter(arrayAccess); + biScan(arrayAccess.getAnnotations(), other.getAnnotations()); + biScan(arrayAccess.getType(), other.getType()); + biScan(arrayAccess.getTypeCasts(), other.getTypeCasts()); + biScan(arrayAccess.getTarget(), other.getTarget()); + biScan(arrayAccess.getIndexExpression(), other.getIndexExpression()); + exit(arrayAccess); } - @Override - public void visitCtArrayTypeReference(CtArrayTypeReference e) { - final CtArrayTypeReference peek = (CtArrayTypeReference) this.stack.peek(); - if (e.getDimensionCount() != peek.getDimensionCount()) { - isNotEqual = true; - return; - } - super.visitCtArrayTypeReference(e); + @java.lang.Override + public void visitCtArrayRead(final spoon.reflect.code.CtArrayRead arrayRead) { + spoon.reflect.code.CtArrayRead other = ((spoon.reflect.code.CtArrayRead) (stack.peek())); + enter(arrayRead); + biScan(arrayRead.getAnnotations(), other.getAnnotations()); + biScan(arrayRead.getType(), other.getType()); + biScan(arrayRead.getTypeCasts(), other.getTypeCasts()); + biScan(arrayRead.getTarget(), other.getTarget()); + biScan(arrayRead.getIndexExpression(), other.getIndexExpression()); + exit(arrayRead); } - @Override - public void visitCtBreak(CtBreak e) { - final CtBreak peek = (CtBreak) this.stack.peek(); - if (!e.getTargetLabel().equals(peek.getTargetLabel())) { - isNotEqual = true; - return; - } - super.visitCtBreak(e); + @java.lang.Override + public void visitCtArrayWrite(final spoon.reflect.code.CtArrayWrite arrayWrite) { + spoon.reflect.code.CtArrayWrite other = ((spoon.reflect.code.CtArrayWrite) (stack.peek())); + enter(arrayWrite); + biScan(arrayWrite.getAnnotations(), other.getAnnotations()); + biScan(arrayWrite.getType(), other.getType()); + biScan(arrayWrite.getTypeCasts(), other.getTypeCasts()); + biScan(arrayWrite.getTarget(), other.getTarget()); + biScan(arrayWrite.getIndexExpression(), other.getIndexExpression()); + exit(arrayWrite); } - @Override - public void visitCtContinue(CtContinue e) { - final CtContinue peek = (CtContinue) this.stack.peek(); - if (!e.getTargetLabel().equals(peek.getTargetLabel())) { - isNotEqual = true; - return; - } - super.visitCtContinue(e); + public void visitCtArrayTypeReference(final spoon.reflect.reference.CtArrayTypeReference reference) { + spoon.reflect.reference.CtArrayTypeReference other = ((spoon.reflect.reference.CtArrayTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getPackage(), other.getPackage()); + biScan(reference.getComponentType(), other.getComponentType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); } - @Override - public void visitCtExecutableReference(CtExecutableReference e) { - final CtExecutableReference peek = (CtExecutableReference) this.stack.peek(); - if (e.isConstructor() != peek.isConstructor()) { - isNotEqual = true; - return; - } - super.visitCtExecutableReference(e); + public void visitCtAssert(final spoon.reflect.code.CtAssert asserted) { + spoon.reflect.code.CtAssert other = ((spoon.reflect.code.CtAssert) (stack.peek())); + enter(asserted); + biScan(asserted.getAnnotations(), other.getAnnotations()); + biScan(asserted.getAssertExpression(), other.getAssertExpression()); + biScan(asserted.getExpression(), other.getExpression()); + exit(asserted); } - @Override - public void visitCtMethod(CtMethod e) { - final CtMethod peek = (CtMethod) this.stack.peek(); - if (e.isDefaultMethod() != peek.isDefaultMethod()) { - isNotEqual = true; - return; - } - super.visitCtMethod(e); + public void visitCtAssignment(final spoon.reflect.code.CtAssignment assignement) { + spoon.reflect.code.CtAssignment other = ((spoon.reflect.code.CtAssignment) (stack.peek())); + enter(assignement); + biScan(assignement.getAnnotations(), other.getAnnotations()); + biScan(assignement.getType(), other.getType()); + biScan(assignement.getTypeCasts(), other.getTypeCasts()); + biScan(assignement.getAssigned(), other.getAssigned()); + biScan(assignement.getAssignment(), other.getAssignment()); + exit(assignement); } - @Override - public void visitCtParameter(CtParameter e) { - final CtParameter peek = (CtParameter) this.stack.peek(); - if (e.isVarArgs() != peek.isVarArgs()) { - isNotEqual = true; - return; - } - super.visitCtParameter(e); + public void visitCtBinaryOperator(final spoon.reflect.code.CtBinaryOperator operator) { + spoon.reflect.code.CtBinaryOperator other = ((spoon.reflect.code.CtBinaryOperator) (stack.peek())); + enter(operator); + biScan(operator.getAnnotations(), other.getAnnotations()); + biScan(operator.getType(), other.getType()); + biScan(operator.getTypeCasts(), other.getTypeCasts()); + biScan(operator.getLeftHandOperand(), other.getLeftHandOperand()); + biScan(operator.getRightHandOperand(), other.getRightHandOperand()); + exit(operator); + } + + public void visitCtBlock(final spoon.reflect.code.CtBlock block) { + spoon.reflect.code.CtBlock other = ((spoon.reflect.code.CtBlock) (stack.peek())); + enter(block); + biScan(block.getAnnotations(), other.getAnnotations()); + biScan(block.getStatements(), other.getStatements()); + exit(block); + } + + public void visitCtBreak(final spoon.reflect.code.CtBreak breakStatement) { + spoon.reflect.code.CtBreak other = ((spoon.reflect.code.CtBreak) (stack.peek())); + enter(breakStatement); + biScan(breakStatement.getAnnotations(), other.getAnnotations()); + exit(breakStatement); + } + + public void visitCtCase(final spoon.reflect.code.CtCase caseStatement) { + spoon.reflect.code.CtCase other = ((spoon.reflect.code.CtCase) (stack.peek())); + enter(caseStatement); + biScan(caseStatement.getAnnotations(), other.getAnnotations()); + biScan(caseStatement.getCaseExpression(), other.getCaseExpression()); + biScan(caseStatement.getStatements(), other.getStatements()); + exit(caseStatement); + } + + public void visitCtCatch(final spoon.reflect.code.CtCatch catchBlock) { + spoon.reflect.code.CtCatch other = ((spoon.reflect.code.CtCatch) (stack.peek())); + enter(catchBlock); + biScan(catchBlock.getAnnotations(), other.getAnnotations()); + biScan(catchBlock.getParameter(), other.getParameter()); + biScan(catchBlock.getBody(), other.getBody()); + exit(catchBlock); + } + + public void visitCtClass(final spoon.reflect.declaration.CtClass ctClass) { + spoon.reflect.declaration.CtClass other = ((spoon.reflect.declaration.CtClass) (stack.peek())); + enter(ctClass); + biScan(ctClass.getAnnotations(), other.getAnnotations()); + biScan(ctClass.getSuperclass(), other.getSuperclass()); + biScan(ctClass.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(ctClass.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(ctClass.getAnonymousExecutables(), other.getAnonymousExecutables()); + biScan(ctClass.getNestedTypes(), other.getNestedTypes()); + biScan(ctClass.getFields(), other.getFields()); + biScan(ctClass.getConstructors(), other.getConstructors()); + biScan(ctClass.getMethods(), other.getMethods()); + exit(ctClass); + } + + public void visitCtConditional(final spoon.reflect.code.CtConditional conditional) { + spoon.reflect.code.CtConditional other = ((spoon.reflect.code.CtConditional) (stack.peek())); + enter(conditional); + biScan(conditional.getAnnotations(), other.getAnnotations()); + biScan(conditional.getCondition(), other.getCondition()); + biScan(conditional.getThenExpression(), other.getThenExpression()); + biScan(conditional.getElseExpression(), other.getElseExpression()); + exit(conditional); + } + + public void visitCtConstructor(final spoon.reflect.declaration.CtConstructor c) { + spoon.reflect.declaration.CtConstructor other = ((spoon.reflect.declaration.CtConstructor) (stack.peek())); + enter(c); + biScan(c.getAnnotations(), other.getAnnotations()); + biScan(c.getParameters(), other.getParameters()); + biScan(c.getThrownTypes(), other.getThrownTypes()); + biScan(c.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(c.getBody(), other.getBody()); + exit(c); + } + + public void visitCtContinue(final spoon.reflect.code.CtContinue continueStatement) { + spoon.reflect.code.CtContinue other = ((spoon.reflect.code.CtContinue) (stack.peek())); + enter(continueStatement); + biScan(continueStatement.getAnnotations(), other.getAnnotations()); + biScan(continueStatement.getLabelledStatement(), other.getLabelledStatement()); + exit(continueStatement); + } + + public void visitCtDo(final spoon.reflect.code.CtDo doLoop) { + spoon.reflect.code.CtDo other = ((spoon.reflect.code.CtDo) (stack.peek())); + enter(doLoop); + biScan(doLoop.getAnnotations(), other.getAnnotations()); + biScan(doLoop.getLoopingExpression(), other.getLoopingExpression()); + biScan(doLoop.getBody(), other.getBody()); + exit(doLoop); + } + + public > void visitCtEnum(final spoon.reflect.declaration.CtEnum ctEnum) { + spoon.reflect.declaration.CtEnum other = ((spoon.reflect.declaration.CtEnum) (stack.peek())); + enter(ctEnum); + biScan(ctEnum.getAnnotations(), other.getAnnotations()); + biScan(ctEnum.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(ctEnum.getFields(), other.getFields()); + biScan(ctEnum.getConstructors(), other.getConstructors()); + biScan(ctEnum.getMethods(), other.getMethods()); + biScan(ctEnum.getNestedTypes(), other.getNestedTypes()); + exit(ctEnum); + } + + public void visitCtExecutableReference(final spoon.reflect.reference.CtExecutableReference reference) { + spoon.reflect.reference.CtExecutableReference other = ((spoon.reflect.reference.CtExecutableReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getParameters(), other.getParameters()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtField(final spoon.reflect.declaration.CtField f) { + spoon.reflect.declaration.CtField other = ((spoon.reflect.declaration.CtField) (stack.peek())); + enter(f); + biScan(f.getAnnotations(), other.getAnnotations()); + biScan(f.getType(), other.getType()); + biScan(f.getDefaultExpression(), other.getDefaultExpression()); + exit(f); + } + + @java.lang.Override + public void visitCtEnumValue(final spoon.reflect.declaration.CtEnumValue enumValue) { + spoon.reflect.declaration.CtEnumValue other = ((spoon.reflect.declaration.CtEnumValue) (stack.peek())); + enter(enumValue); + biScan(enumValue.getAnnotations(), other.getAnnotations()); + biScan(enumValue.getType(), other.getType()); + biScan(enumValue.getDefaultExpression(), other.getDefaultExpression()); + exit(enumValue); + } + + @java.lang.Override + public void visitCtThisAccess(final spoon.reflect.code.CtThisAccess thisAccess) { + spoon.reflect.code.CtThisAccess other = ((spoon.reflect.code.CtThisAccess) (stack.peek())); + enter(thisAccess); + biScan(thisAccess.getType(), other.getType()); + biScan(thisAccess.getTypeCasts(), other.getTypeCasts()); + biScan(thisAccess.getTarget(), other.getTarget()); + exit(thisAccess); + } + + public void visitCtAnnotationFieldAccess(final spoon.reflect.code.CtAnnotationFieldAccess annotationFieldAccess) { + spoon.reflect.code.CtAnnotationFieldAccess other = ((spoon.reflect.code.CtAnnotationFieldAccess) (stack.peek())); + enter(annotationFieldAccess); + biScan(annotationFieldAccess.getAnnotations(), other.getAnnotations()); + biScan(annotationFieldAccess.getType(), other.getType()); + biScan(annotationFieldAccess.getTypeCasts(), other.getTypeCasts()); + biScan(annotationFieldAccess.getTarget(), other.getTarget()); + biScan(annotationFieldAccess.getVariable(), other.getVariable()); + exit(annotationFieldAccess); + } + + public void visitCtFieldReference(final spoon.reflect.reference.CtFieldReference reference) { + spoon.reflect.reference.CtFieldReference other = ((spoon.reflect.reference.CtFieldReference) (stack.peek())); + enter(reference); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtFor(final spoon.reflect.code.CtFor forLoop) { + spoon.reflect.code.CtFor other = ((spoon.reflect.code.CtFor) (stack.peek())); + enter(forLoop); + biScan(forLoop.getAnnotations(), other.getAnnotations()); + biScan(forLoop.getForInit(), other.getForInit()); + biScan(forLoop.getExpression(), other.getExpression()); + biScan(forLoop.getForUpdate(), other.getForUpdate()); + biScan(forLoop.getBody(), other.getBody()); + exit(forLoop); + } + + public void visitCtForEach(final spoon.reflect.code.CtForEach foreach) { + spoon.reflect.code.CtForEach other = ((spoon.reflect.code.CtForEach) (stack.peek())); + enter(foreach); + biScan(foreach.getAnnotations(), other.getAnnotations()); + biScan(foreach.getVariable(), other.getVariable()); + biScan(foreach.getExpression(), other.getExpression()); + biScan(foreach.getBody(), other.getBody()); + exit(foreach); + } + + public void visitCtIf(final spoon.reflect.code.CtIf ifElement) { + spoon.reflect.code.CtIf other = ((spoon.reflect.code.CtIf) (stack.peek())); + enter(ifElement); + biScan(ifElement.getAnnotations(), other.getAnnotations()); + biScan(ifElement.getCondition(), other.getCondition()); + biScan(((spoon.reflect.code.CtStatement) (ifElement.getThenStatement())), other.getThenStatement()); + biScan(((spoon.reflect.code.CtStatement) (ifElement.getElseStatement())), other.getElseStatement()); + exit(ifElement); + } + + public void visitCtInterface(final spoon.reflect.declaration.CtInterface intrface) { + spoon.reflect.declaration.CtInterface other = ((spoon.reflect.declaration.CtInterface) (stack.peek())); + enter(intrface); + biScan(intrface.getAnnotations(), other.getAnnotations()); + biScan(intrface.getSuperInterfaces(), other.getSuperInterfaces()); + biScan(intrface.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(intrface.getNestedTypes(), other.getNestedTypes()); + biScan(intrface.getFields(), other.getFields()); + biScan(intrface.getMethods(), other.getMethods()); + exit(intrface); + } + + public void visitCtInvocation(final spoon.reflect.code.CtInvocation invocation) { + spoon.reflect.code.CtInvocation other = ((spoon.reflect.code.CtInvocation) (stack.peek())); + enter(invocation); + biScan(invocation.getAnnotations(), other.getAnnotations()); + biScan(invocation.getTypeCasts(), other.getTypeCasts()); + biScan(invocation.getTarget(), other.getTarget()); + biScan(invocation.getExecutable(), other.getExecutable()); + biScan(invocation.getArguments(), other.getArguments()); + exit(invocation); + } + + public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { + spoon.reflect.code.CtLiteral other = ((spoon.reflect.code.CtLiteral) (stack.peek())); + enter(literal); + biScan(literal.getAnnotations(), other.getAnnotations()); + biScan(literal.getType(), other.getType()); + biScan(literal.getValue(), other.getValue()); + biScan(literal.getTypeCasts(), other.getTypeCasts()); + exit(literal); + } + + public void visitCtLocalVariable(final spoon.reflect.code.CtLocalVariable localVariable) { + spoon.reflect.code.CtLocalVariable other = ((spoon.reflect.code.CtLocalVariable) (stack.peek())); + enter(localVariable); + biScan(localVariable.getAnnotations(), other.getAnnotations()); + biScan(localVariable.getType(), other.getType()); + biScan(localVariable.getDefaultExpression(), other.getDefaultExpression()); + exit(localVariable); + } + + public void visitCtLocalVariableReference(final spoon.reflect.reference.CtLocalVariableReference reference) { + spoon.reflect.reference.CtLocalVariableReference other = ((spoon.reflect.reference.CtLocalVariableReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtCatchVariable(final spoon.reflect.code.CtCatchVariable catchVariable) { + spoon.reflect.code.CtCatchVariable other = ((spoon.reflect.code.CtCatchVariable) (stack.peek())); + enter(catchVariable); + biScan(catchVariable.getAnnotations(), other.getAnnotations()); + biScan(catchVariable.getType(), other.getType()); + exit(catchVariable); + } + + public void visitCtCatchVariableReference(final spoon.reflect.reference.CtCatchVariableReference reference) { + spoon.reflect.reference.CtCatchVariableReference other = ((spoon.reflect.reference.CtCatchVariableReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtMethod(final spoon.reflect.declaration.CtMethod m) { + spoon.reflect.declaration.CtMethod other = ((spoon.reflect.declaration.CtMethod) (stack.peek())); + enter(m); + biScan(m.getAnnotations(), other.getAnnotations()); + biScan(m.getFormalTypeParameters(), other.getFormalTypeParameters()); + biScan(m.getType(), other.getType()); + biScan(m.getParameters(), other.getParameters()); + biScan(m.getThrownTypes(), other.getThrownTypes()); + biScan(m.getBody(), other.getBody()); + exit(m); + } + + public void visitCtNewArray(final spoon.reflect.code.CtNewArray newArray) { + spoon.reflect.code.CtNewArray other = ((spoon.reflect.code.CtNewArray) (stack.peek())); + enter(newArray); + biScan(newArray.getAnnotations(), other.getAnnotations()); + biScan(newArray.getType(), other.getType()); + biScan(newArray.getTypeCasts(), other.getTypeCasts()); + biScan(newArray.getElements(), other.getElements()); + biScan(newArray.getDimensionExpressions(), other.getDimensionExpressions()); + exit(newArray); + } + + @java.lang.Override + public void visitCtConstructorCall(final spoon.reflect.code.CtConstructorCall ctConstructorCall) { + spoon.reflect.code.CtConstructorCall other = ((spoon.reflect.code.CtConstructorCall) (stack.peek())); + enter(ctConstructorCall); + biScan(ctConstructorCall.getAnnotations(), other.getAnnotations()); + biScan(ctConstructorCall.getTypeCasts(), other.getTypeCasts()); + biScan(ctConstructorCall.getExecutable(), other.getExecutable()); + biScan(ctConstructorCall.getTarget(), other.getTarget()); + biScan(ctConstructorCall.getArguments(), other.getArguments()); + exit(ctConstructorCall); + } + + public void visitCtNewClass(final spoon.reflect.code.CtNewClass newClass) { + spoon.reflect.code.CtNewClass other = ((spoon.reflect.code.CtNewClass) (stack.peek())); + enter(newClass); + biScan(newClass.getAnnotations(), other.getAnnotations()); + biScan(newClass.getTypeCasts(), other.getTypeCasts()); + biScan(newClass.getExecutable(), other.getExecutable()); + biScan(newClass.getTarget(), other.getTarget()); + biScan(newClass.getArguments(), other.getArguments()); + biScan(newClass.getAnonymousClass(), other.getAnonymousClass()); + exit(newClass); + } + + @java.lang.Override + public void visitCtLambda(final spoon.reflect.code.CtLambda lambda) { + spoon.reflect.code.CtLambda other = ((spoon.reflect.code.CtLambda) (stack.peek())); + enter(lambda); + biScan(lambda.getAnnotations(), other.getAnnotations()); + biScan(lambda.getType(), other.getType()); + biScan(lambda.getTypeCasts(), other.getTypeCasts()); + biScan(lambda.getParameters(), other.getParameters()); + biScan(lambda.getBody(), other.getBody()); + biScan(lambda.getExpression(), other.getExpression()); + exit(lambda); + } + + @java.lang.Override + public > void visitCtExecutableReferenceExpression(final spoon.reflect.code.CtExecutableReferenceExpression expression) { + spoon.reflect.code.CtExecutableReferenceExpression other = ((spoon.reflect.code.CtExecutableReferenceExpression) (stack.peek())); + enter(expression); + biScan(expression.getType(), other.getType()); + biScan(expression.getTypeCasts(), other.getTypeCasts()); + biScan(expression.getExecutable(), other.getExecutable()); + biScan(expression.getTarget(), other.getTarget()); + exit(expression); + } + + public void visitCtOperatorAssignment(final spoon.reflect.code.CtOperatorAssignment assignment) { + spoon.reflect.code.CtOperatorAssignment other = ((spoon.reflect.code.CtOperatorAssignment) (stack.peek())); + enter(assignment); + biScan(assignment.getAnnotations(), other.getAnnotations()); + biScan(assignment.getType(), other.getType()); + biScan(assignment.getTypeCasts(), other.getTypeCasts()); + biScan(assignment.getAssigned(), other.getAssigned()); + biScan(assignment.getAssignment(), other.getAssignment()); + exit(assignment); + } + + public void visitCtPackage(final spoon.reflect.declaration.CtPackage ctPackage) { + spoon.reflect.declaration.CtPackage other = ((spoon.reflect.declaration.CtPackage) (stack.peek())); + enter(ctPackage); + biScan(ctPackage.getAnnotations(), other.getAnnotations()); + biScan(ctPackage.getPackages(), other.getPackages()); + biScan(ctPackage.getTypes(), other.getTypes()); + exit(ctPackage); + } + + public void visitCtPackageReference(final spoon.reflect.reference.CtPackageReference reference) { + spoon.reflect.reference.CtPackageReference other = ((spoon.reflect.reference.CtPackageReference) (stack.peek())); + enter(reference); + exit(reference); + } + + public void visitCtParameter(final spoon.reflect.declaration.CtParameter parameter) { + spoon.reflect.declaration.CtParameter other = ((spoon.reflect.declaration.CtParameter) (stack.peek())); + enter(parameter); + biScan(parameter.getAnnotations(), other.getAnnotations()); + biScan(parameter.getType(), other.getType()); + exit(parameter); + } + + public void visitCtParameterReference(final spoon.reflect.reference.CtParameterReference reference) { + spoon.reflect.reference.CtParameterReference other = ((spoon.reflect.reference.CtParameterReference) (stack.peek())); + enter(reference); + biScan(reference.getType(), other.getType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + public void visitCtReturn(final spoon.reflect.code.CtReturn returnStatement) { + spoon.reflect.code.CtReturn other = ((spoon.reflect.code.CtReturn) (stack.peek())); + enter(returnStatement); + biScan(returnStatement.getAnnotations(), other.getAnnotations()); + biScan(returnStatement.getReturnedExpression(), other.getReturnedExpression()); + exit(returnStatement); + } + + public void visitCtStatementList(final spoon.reflect.code.CtStatementList statements) { + spoon.reflect.code.CtStatementList other = ((spoon.reflect.code.CtStatementList) (stack.peek())); + enter(statements); + biScan(statements.getAnnotations(), other.getAnnotations()); + biScan(statements.getStatements(), other.getStatements()); + exit(statements); + } + + public void visitCtSwitch(final spoon.reflect.code.CtSwitch switchStatement) { + spoon.reflect.code.CtSwitch other = ((spoon.reflect.code.CtSwitch) (stack.peek())); + enter(switchStatement); + biScan(switchStatement.getAnnotations(), other.getAnnotations()); + biScan(switchStatement.getSelector(), other.getSelector()); + biScan(switchStatement.getCases(), other.getCases()); + exit(switchStatement); + } + + public void visitCtSynchronized(final spoon.reflect.code.CtSynchronized synchro) { + spoon.reflect.code.CtSynchronized other = ((spoon.reflect.code.CtSynchronized) (stack.peek())); + enter(synchro); + biScan(synchro.getAnnotations(), other.getAnnotations()); + biScan(synchro.getExpression(), other.getExpression()); + biScan(synchro.getBlock(), other.getBlock()); + exit(synchro); + } + + public void visitCtThrow(final spoon.reflect.code.CtThrow throwStatement) { + spoon.reflect.code.CtThrow other = ((spoon.reflect.code.CtThrow) (stack.peek())); + enter(throwStatement); + biScan(throwStatement.getAnnotations(), other.getAnnotations()); + biScan(throwStatement.getThrownExpression(), other.getThrownExpression()); + exit(throwStatement); + } + + public void visitCtTry(final spoon.reflect.code.CtTry tryBlock) { + spoon.reflect.code.CtTry other = ((spoon.reflect.code.CtTry) (stack.peek())); + enter(tryBlock); + biScan(tryBlock.getAnnotations(), other.getAnnotations()); + biScan(tryBlock.getBody(), other.getBody()); + biScan(tryBlock.getCatchers(), other.getCatchers()); + biScan(tryBlock.getFinalizer(), other.getFinalizer()); + exit(tryBlock); + } + + @java.lang.Override + public void visitCtTryWithResource(final spoon.reflect.code.CtTryWithResource tryWithResource) { + spoon.reflect.code.CtTryWithResource other = ((spoon.reflect.code.CtTryWithResource) (stack.peek())); + enter(tryWithResource); + biScan(tryWithResource.getAnnotations(), other.getAnnotations()); + biScan(tryWithResource.getResources(), other.getResources()); + biScan(tryWithResource.getBody(), other.getBody()); + biScan(tryWithResource.getCatchers(), other.getCatchers()); + biScan(tryWithResource.getFinalizer(), other.getFinalizer()); + exit(tryWithResource); + } + + public void visitCtTypeParameterReference(final spoon.reflect.reference.CtTypeParameterReference ref) { + spoon.reflect.reference.CtTypeParameterReference other = ((spoon.reflect.reference.CtTypeParameterReference) (stack.peek())); + enter(ref); + biScan(ref.getPackage(), other.getPackage()); + biScan(ref.getDeclaringType(), other.getDeclaringType()); + biScan(ref.getAnnotations(), other.getAnnotations()); + biScan(ref.getBoundingType(), other.getBoundingType()); + exit(ref); + } + + @java.lang.Override + public void visitCtIntersectionTypeReference(final spoon.reflect.reference.CtIntersectionTypeReference reference) { + spoon.reflect.reference.CtIntersectionTypeReference other = ((spoon.reflect.reference.CtIntersectionTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getBounds(), other.getBounds()); + exit(reference); + } + + public void visitCtTypeReference(final spoon.reflect.reference.CtTypeReference reference) { + spoon.reflect.reference.CtTypeReference other = ((spoon.reflect.reference.CtTypeReference) (stack.peek())); + enter(reference); + biScan(reference.getPackage(), other.getPackage()); + biScan(reference.getDeclaringType(), other.getDeclaringType()); + biScan(reference.getAnnotations(), other.getAnnotations()); + exit(reference); + } + + @java.lang.Override + public void visitCtCircularTypeReference(final spoon.reflect.internal.CtCircularTypeReference reference) { + spoon.reflect.internal.CtCircularTypeReference other = ((spoon.reflect.internal.CtCircularTypeReference) (stack.peek())); + enter(reference); + exit(reference); + } + + @java.lang.Override + public void visitCtTypeAccess(final spoon.reflect.code.CtTypeAccess typeAccess) { + spoon.reflect.code.CtTypeAccess other = ((spoon.reflect.code.CtTypeAccess) (stack.peek())); + enter(typeAccess); + biScan(typeAccess.getAnnotations(), other.getAnnotations()); + biScan(typeAccess.getType(), other.getType()); + biScan(typeAccess.getTypeCasts(), other.getTypeCasts()); + biScan(typeAccess.getAccessedType(), other.getAccessedType()); + exit(typeAccess); + } + + public void visitCtUnaryOperator(final spoon.reflect.code.CtUnaryOperator operator) { + spoon.reflect.code.CtUnaryOperator other = ((spoon.reflect.code.CtUnaryOperator) (stack.peek())); + enter(operator); + biScan(operator.getAnnotations(), other.getAnnotations()); + biScan(operator.getType(), other.getType()); + biScan(operator.getTypeCasts(), other.getTypeCasts()); + biScan(operator.getOperand(), other.getOperand()); + exit(operator); + } + + @java.lang.Override + public void visitCtVariableRead(final spoon.reflect.code.CtVariableRead variableRead) { + spoon.reflect.code.CtVariableRead other = ((spoon.reflect.code.CtVariableRead) (stack.peek())); + enter(variableRead); + biScan(variableRead.getAnnotations(), other.getAnnotations()); + biScan(variableRead.getType(), other.getType()); + biScan(variableRead.getTypeCasts(), other.getTypeCasts()); + biScan(variableRead.getVariable(), other.getVariable()); + exit(variableRead); + } + + @java.lang.Override + public void visitCtVariableWrite(final spoon.reflect.code.CtVariableWrite variableWrite) { + spoon.reflect.code.CtVariableWrite other = ((spoon.reflect.code.CtVariableWrite) (stack.peek())); + enter(variableWrite); + biScan(variableWrite.getAnnotations(), other.getAnnotations()); + biScan(variableWrite.getType(), other.getType()); + biScan(variableWrite.getTypeCasts(), other.getTypeCasts()); + biScan(variableWrite.getVariable(), other.getVariable()); + exit(variableWrite); + } + + public void visitCtWhile(final spoon.reflect.code.CtWhile whileLoop) { + spoon.reflect.code.CtWhile other = ((spoon.reflect.code.CtWhile) (stack.peek())); + enter(whileLoop); + biScan(whileLoop.getAnnotations(), other.getAnnotations()); + biScan(whileLoop.getLoopingExpression(), other.getLoopingExpression()); + biScan(whileLoop.getBody(), other.getBody()); + exit(whileLoop); + } + + public void visitCtCodeSnippetExpression(final spoon.reflect.code.CtCodeSnippetExpression expression) { + spoon.reflect.code.CtCodeSnippetExpression other = ((spoon.reflect.code.CtCodeSnippetExpression) (stack.peek())); + enter(expression); + exit(expression); + } + + public void visitCtCodeSnippetStatement(final spoon.reflect.code.CtCodeSnippetStatement statement) { + spoon.reflect.code.CtCodeSnippetStatement other = ((spoon.reflect.code.CtCodeSnippetStatement) (stack.peek())); + enter(statement); + exit(statement); + } + + public void visitCtUnboundVariableReference(final spoon.reflect.reference.CtUnboundVariableReference reference) { + spoon.reflect.reference.CtUnboundVariableReference other = ((spoon.reflect.reference.CtUnboundVariableReference) (stack.peek())); + enter(reference); + exit(reference); + } + + @java.lang.Override + public void visitCtFieldRead(final spoon.reflect.code.CtFieldRead fieldRead) { + spoon.reflect.code.CtFieldRead other = ((spoon.reflect.code.CtFieldRead) (stack.peek())); + enter(fieldRead); + biScan(fieldRead.getAnnotations(), other.getAnnotations()); + biScan(fieldRead.getTypeCasts(), other.getTypeCasts()); + biScan(fieldRead.getTarget(), other.getTarget()); + biScan(fieldRead.getVariable(), other.getVariable()); + exit(fieldRead); + } + + @java.lang.Override + public void visitCtFieldWrite(final spoon.reflect.code.CtFieldWrite fieldWrite) { + spoon.reflect.code.CtFieldWrite other = ((spoon.reflect.code.CtFieldWrite) (stack.peek())); + enter(fieldWrite); + biScan(fieldWrite.getAnnotations(), other.getAnnotations()); + biScan(fieldWrite.getTypeCasts(), other.getTypeCasts()); + biScan(fieldWrite.getTarget(), other.getTarget()); + biScan(fieldWrite.getVariable(), other.getVariable()); + exit(fieldWrite); + } + + @java.lang.Override + public void visitCtSuperAccess(final spoon.reflect.code.CtSuperAccess f) { + spoon.reflect.code.CtSuperAccess other = ((spoon.reflect.code.CtSuperAccess) (stack.peek())); + enter(f); + biScan(f.getAnnotations(), other.getAnnotations()); + biScan(f.getType(), other.getType()); + biScan(f.getTypeCasts(), other.getTypeCasts()); + biScan(f.getTarget(), other.getTarget()); + exit(f); + } + + @java.lang.Override + public void visitCtComment(final spoon.reflect.code.CtComment comment) { + spoon.reflect.code.CtComment other = ((spoon.reflect.code.CtComment) (stack.peek())); + enter(comment); + exit(comment); } } + diff --git a/src/test/java/spoon/reflect/visitor/CtScannerTest.java b/src/test/java/spoon/reflect/visitor/CtScannerTest.java index dcff251827f..111b8bd895f 100644 --- a/src/test/java/spoon/reflect/visitor/CtScannerTest.java +++ b/src/test/java/spoon/reflect/visitor/CtScannerTest.java @@ -20,10 +20,12 @@ import org.junit.Test; import spoon.Launcher; import spoon.generating.CtBiScannerGenerator; +import spoon.generating.EqualsVisitorGenerator; import spoon.generating.ReplacementVisitorGenerator; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.processors.CheckScannerProcessor; +import spoon.support.visitor.equals.EqualsVisitor; import spoon.support.visitor.replace.ReplacementVisitor; import java.io.File; @@ -57,26 +59,6 @@ public void testScannerContract() throws Exception { @Test public void testGenerateReplacementVisitor() throws Exception { - class RegexFilter implements Filter> { - private final Pattern regex; - - private RegexFilter(String regex) { - if (regex == null) { - throw new IllegalArgumentException(); - } - this.regex = Pattern.compile(regex); - } - - public boolean matches(CtType element) { - Matcher m = regex.matcher(element.getQualifiedName()); - return m.matches(); - } - - public Class getType() { - return CtElement.class; - } - } - final Launcher launcher = new Launcher(); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setGenerateJavadoc(true); @@ -100,26 +82,6 @@ public Class getType() { @Test public void testGenerateCtBiScanner() throws Exception { - class RegexFilter implements Filter> { - private final Pattern regex; - - private RegexFilter(String regex) { - if (regex == null) { - throw new IllegalArgumentException(); - } - this.regex = Pattern.compile(regex); - } - - public boolean matches(CtType element) { - Matcher m = regex.matcher(element.getQualifiedName()); - return m.matches(); - } - - public Class getType() { - return CtElement.class; - } - } - final Launcher launcher = new Launcher(); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setGenerateJavadoc(true); @@ -140,4 +102,47 @@ public Class getType() { assertThat(build(new File("./src/main/java/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)) .isEqualTo(build(new File("./target/generated/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)); } + + @Test + public void testGenerateEqualsVisitor() throws Exception { + final Launcher launcher = new Launcher(); + launcher.getEnvironment().setNoClasspath(true); + launcher.getEnvironment().setGenerateJavadoc(true); + launcher.getEnvironment().useTabulations(true); + launcher.setSourceOutputDirectory("./target/generated/"); + // interfaces. + launcher.addInputResource("./src/main/java/spoon/reflect/code"); + launcher.addInputResource("./src/main/java/spoon/reflect/declaration"); + launcher.addInputResource("./src/main/java/spoon/reflect/reference"); + launcher.addInputResource("./src/main/java/spoon/reflect/internal"); + // Utils. + launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtBiScanner.java"); + launcher.addInputResource("./src/main/java/spoon/generating/equals/"); + launcher.addProcessor(new EqualsVisitorGenerator()); + launcher.setOutputFilter(new RegexFilter("spoon.support.visitor.equals.EqualsVisitor")); + launcher.run(); + + assertThat(build(new File("./src/main/java/spoon/support/visitor/equals/EqualsVisitor.java")).Class().get(EqualsVisitor.class)) + .isEqualTo(build(new File("./target/generated/spoon/support/visitor/equals/EqualsVisitor.java")).Class().get(EqualsVisitor.class)); + } + + private class RegexFilter implements Filter> { + private final Pattern regex; + + private RegexFilter(String regex) { + if (regex == null) { + throw new IllegalArgumentException(); + } + this.regex = Pattern.compile(regex); + } + + public boolean matches(CtType element) { + Matcher m = regex.matcher(element.getQualifiedName()); + return m.matches(); + } + + public Class getType() { + return CtElement.class; + } + } } From 4389961adde0fbd8faa787463af64eecf90dbef7 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Thu, 26 May 2016 11:24:22 +0200 Subject: [PATCH 3/4] refactor: Renames EqualsChecker, *Generator and remove getValue. --- .../generating/CtBiScannerGenerator.java | 64 +++++++++++++-- .../generating/EqualsVisitorGenerator.java | 44 ++++++++-- .../equals/EqualsVisitorScanner.java | 61 -------------- ...isitor.java => EqualsVisitorTemplate.java} | 8 +- .../scanner/CtBiScannerScanner.java | 80 ------------------- ...iScanner.java => CtBiScannerTemplate.java} | 55 ++++--------- .../spoon/reflect/visitor/CtBiScanner.java | 51 +++--------- ...kerInheritance.java => EqualsChecker.java} | 46 +++++++++-- .../support/visitor/equals/EqualsVisitor.java | 3 +- 9 files changed, 170 insertions(+), 242 deletions(-) delete mode 100644 src/main/java/spoon/generating/equals/EqualsVisitorScanner.java rename src/main/java/spoon/generating/equals/{EqualsVisitor.java => EqualsVisitorTemplate.java} (84%) delete mode 100644 src/main/java/spoon/generating/scanner/CtBiScannerScanner.java rename src/main/java/spoon/generating/scanner/{CtBiScanner.java => CtBiScannerTemplate.java} (70%) rename src/main/java/spoon/support/visitor/equals/{EqualsCheckerInheritance.java => EqualsChecker.java} (83%) diff --git a/src/main/java/spoon/generating/CtBiScannerGenerator.java b/src/main/java/spoon/generating/CtBiScannerGenerator.java index cffb6d62328..89ea6ea1dfc 100644 --- a/src/main/java/spoon/generating/CtBiScannerGenerator.java +++ b/src/main/java/spoon/generating/CtBiScannerGenerator.java @@ -16,24 +16,28 @@ */ package spoon.generating; -import spoon.generating.scanner.CtBiScannerScanner; import spoon.processing.AbstractProcessor; +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.ModifierKind; +import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.ReferenceFilter; import java.util.List; -import static spoon.generating.scanner.CtBiScannerScanner.GENERATING_BISCANNER_PACKAGE; -import static spoon.generating.scanner.CtBiScannerScanner.GENERATING_BISCANNER; -import static spoon.generating.scanner.CtBiScannerScanner.TARGET_BISCANNER_PACKAGE; - public class CtBiScannerGenerator extends AbstractProcessor> { + 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); @@ -45,12 +49,59 @@ public void process(CtType element) { .get(GENERATING_BISCANNER_PACKAGE + ".PeekElementTemplate") .getMethod("statement") .getBody().getStatement(0); - new CtBiScannerScanner(createBiScanner(), peekElement).scan(getFactory().Class().get(CtScanner.class)); + final CtClass target = createBiScanner(); + + new CtScanner() { + @Override + public void visitCtMethod(CtMethod element) { + if (!element.getSimpleName().startsWith("visitCt")) { + return; + } + + Factory factory = element.getFactory(); + CtMethod 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); + } + + target.addMethod(clone); + } + }.scan(getFactory().Class().get(CtScanner.class)); } private CtClass createBiScanner() { final CtPackage aPackage = getFactory().Package().getOrCreate(TARGET_BISCANNER_PACKAGE); final CtClass target = getFactory().Class().get(GENERATING_BISCANNER); + target.setSimpleName("CtBiScanner"); target.addModifier(ModifierKind.PUBLIC); aPackage.addType(target); final List references = target.getReferences(new ReferenceFilter() { @@ -65,6 +116,7 @@ public Class getType() { } }); for (CtTypeReference reference : references) { + reference.setSimpleName("CtBiScanner"); reference.setPackage(aPackage.getReference()); } return target; diff --git a/src/main/java/spoon/generating/EqualsVisitorGenerator.java b/src/main/java/spoon/generating/EqualsVisitorGenerator.java index c3995a1b2c9..11579e6fa69 100644 --- a/src/main/java/spoon/generating/EqualsVisitorGenerator.java +++ b/src/main/java/spoon/generating/EqualsVisitorGenerator.java @@ -16,29 +16,62 @@ */ package spoon.generating; -import spoon.generating.equals.EqualsVisitorScanner; import spoon.processing.AbstractManualProcessor; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.CtBiScanner; +import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.ReferenceFilter; +import spoon.support.visitor.equals.IgnoredByEquals; import java.util.List; -import static spoon.generating.equals.EqualsVisitorScanner.GENERATING_EQUALS; -import static spoon.generating.equals.EqualsVisitorScanner.TARGET_EQUALS_PACKAGE; - public class EqualsVisitorGenerator extends AbstractManualProcessor { + private static final String TARGET_EQUALS_PACKAGE = "spoon.support.visitor.equals"; + private static final String GENERATING_EQUALS_PACKAGE = "spoon.generating.equals"; + private static final String GENERATING_EQUALS = GENERATING_EQUALS_PACKAGE + ".EqualsVisitorTemplate"; + @Override public void process() { - new EqualsVisitorScanner(createEqualsVisitor()).scan(getFactory().Class().get(CtBiScanner.class)); + final CtClass target = createEqualsVisitor(); + new CtScanner() { + @Override + public void visitCtMethod(CtMethod element) { + if (!element.getSimpleName().startsWith("visitCt")) { + return; + } + + Factory factory = element.getFactory(); + CtMethod clone = factory.Core().clone(element); + + final CtAnnotation ignoredAnnotation = factory.Core().createAnnotation(); + ignoredAnnotation.setAnnotationType(factory.Type().createReference(IgnoredByEquals.class)); + + for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) { + final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0); + if (targetInvocation.getExecutable().getExecutableDeclaration().getAnnotations().contains(ignoredAnnotation)) { + clone.getBody().getStatement(i--).delete(); + continue; + } + CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i)); + clone.getBody().getStatement(i).replace(replace); + } + + target.addMethod(clone); + } + }.scan(getFactory().Class().get(CtBiScanner.class)); } private CtClass createEqualsVisitor() { final CtPackage aPackage = getFactory().Package().getOrCreate(TARGET_EQUALS_PACKAGE); final CtClass target = getFactory().Class().get(GENERATING_EQUALS); + target.setSimpleName("EqualsVisitor"); target.addModifier(ModifierKind.PUBLIC); aPackage.addType(target); final List references = target.getReferences(new ReferenceFilter() { @@ -53,6 +86,7 @@ public Class getType() { } }); for (CtTypeReference reference : references) { + reference.setSimpleName("EqualsVisitor"); reference.setPackage(aPackage.getReference()); } return target; diff --git a/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java b/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java deleted file mode 100644 index 8efc8b6a384..00000000000 --- a/src/main/java/spoon/generating/equals/EqualsVisitorScanner.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (C) 2006-2015 INRIA and contributors - * Spoon - http://spoon.gforge.inria.fr/ - * - * This software is governed by the CeCILL-C License under French law and - * abiding by the rules of distribution of free software. You can use, modify - * and/or redistribute the software under the terms of the CeCILL-C license as - * circulated by CEA, CNRS and INRIA at http://www.cecill.info. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. - */ -package spoon.generating.equals; - -import spoon.reflect.code.CtInvocation; -import spoon.reflect.declaration.CtAnnotation; -import spoon.reflect.declaration.CtClass; -import spoon.reflect.declaration.CtMethod; -import spoon.reflect.factory.Factory; -import spoon.reflect.visitor.CtScanner; -import spoon.support.visitor.equals.IgnoredByEquals; - -public class EqualsVisitorScanner extends CtScanner { - public static final String TARGET_EQUALS_PACKAGE = "spoon.support.visitor.equals"; - public static final String GENERATING_EQUALS_PACKAGE = "spoon.generating.equals"; - public static final String GENERATING_EQUALS = GENERATING_EQUALS_PACKAGE + ".EqualsVisitor"; - private CtClass target; - - public EqualsVisitorScanner(CtClass target) { - this.target = target; - } - - @Override - public void visitCtMethod(CtMethod element) { - if (!element.getSimpleName().startsWith("visitCt")) { - return; - } - - Factory factory = element.getFactory(); - CtMethod clone = factory.Core().clone(element); - - final CtAnnotation ignoredAnnotation = factory.Core().createAnnotation(); - ignoredAnnotation.setAnnotationType(factory.Type().createReference(IgnoredByEquals.class)); - - for (int i = 2; i < clone.getBody().getStatements().size() - 1; i++) { - final CtInvocation targetInvocation = (CtInvocation) ((CtInvocation) clone.getBody().getStatement(i)).getArguments().get(0); - if (targetInvocation.getExecutable().getExecutableDeclaration().getAnnotations().contains(ignoredAnnotation)) { - clone.getBody().getStatement(i--).delete(); - continue; - } - CtInvocation replace = (CtInvocation) factory.Core().clone(clone.getBody().getStatement(i)); - clone.getBody().getStatement(i).replace(replace); - } - - target.addMethod(clone); - } -} diff --git a/src/main/java/spoon/generating/equals/EqualsVisitor.java b/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java similarity index 84% rename from src/main/java/spoon/generating/equals/EqualsVisitor.java rename to src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java index 6f011721bc8..2b8c8f2bbfe 100644 --- a/src/main/java/spoon/generating/equals/EqualsVisitor.java +++ b/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java @@ -18,19 +18,19 @@ import spoon.reflect.declaration.CtElement; import spoon.reflect.visitor.CtBiScanner; -import spoon.support.visitor.equals.EqualsCheckerInheritance; +import spoon.support.visitor.equals.EqualsChecker; /** * Used to check equality between an element and another one. * * This class is generated automatically by the processor {@link spoon.generating.EqualsVisitorGenerator}. */ -class EqualsVisitor extends CtBiScanner { +class EqualsVisitorTemplate extends CtBiScanner { public static boolean equals(CtElement element, CtElement other) { - return !new EqualsVisitor().biScan(element, other); + return !new EqualsVisitorTemplate().biScan(element, other); } - private final EqualsCheckerInheritance checker = new EqualsCheckerInheritance(); + private final EqualsChecker checker = new EqualsChecker(); @Override protected void enter(CtElement e) { diff --git a/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java b/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java deleted file mode 100644 index 44a24f2facd..00000000000 --- a/src/main/java/spoon/generating/scanner/CtBiScannerScanner.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (C) 2006-2015 INRIA and contributors - * Spoon - http://spoon.gforge.inria.fr/ - * - * This software is governed by the CeCILL-C License under French law and - * abiding by the rules of distribution of free software. You can use, modify - * and/or redistribute the software under the terms of the CeCILL-C license as - * circulated by CEA, CNRS and INRIA at http://www.cecill.info. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. - */ -package spoon.generating.scanner; - -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.factory.Factory; -import spoon.reflect.reference.CtTypeReference; -import spoon.reflect.visitor.CtScanner; - -public class CtBiScannerScanner extends CtScanner { - public static final String TARGET_BISCANNER_PACKAGE = "spoon.reflect.visitor"; - public static final String GENERATING_BISCANNER_PACKAGE = "spoon.generating.scanner"; - public static final String GENERATING_BISCANNER = GENERATING_BISCANNER_PACKAGE + ".CtBiScanner"; - private CtClass target; - private CtLocalVariable peekTemplate; - - public CtBiScannerScanner(CtClass target, CtLocalVariable peekTemplate) { - this.target = target; - this.peekTemplate = peekTemplate; - } - - @Override - public void visitCtMethod(CtMethod element) { - if (!element.getSimpleName().startsWith("visitCt")) { - return; - } - - Factory factory = element.getFactory(); - CtMethod clone = factory.Core().clone(element); - - // Peek element from Stack. - final CtLocalVariable peek = factory.Core().clone(peekTemplate); - 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); - 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); - } - - target.addMethod(clone); - } -} diff --git a/src/main/java/spoon/generating/scanner/CtBiScanner.java b/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java similarity index 70% rename from src/main/java/spoon/generating/scanner/CtBiScanner.java rename to src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java index 75dae76c004..f31f25faba5 100644 --- a/src/main/java/spoon/generating/scanner/CtBiScanner.java +++ b/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java @@ -16,13 +16,13 @@ */ package spoon.generating.scanner; -import spoon.SpoonException; import spoon.reflect.declaration.CtElement; import spoon.reflect.visitor.CtVisitor; import java.util.Collection; -import java.util.Map; +import java.util.Set; import java.util.Stack; +import java.util.TreeSet; /** * This visitor implements a deep-search scan on the model for 2 elements. @@ -30,9 +30,11 @@ * Ensures that all children nodes are visited once, a visit means three method * calls, one call to "enter", one call to "exit" and one call to biScan. * + * This class is generated automatically by the processor {@link spoon.generating.CtBiScannerGenerator}. + * * Is used by EqualsVisitor. */ -abstract class CtBiScanner implements CtVisitor { +abstract class CtBiScannerTemplate implements CtVisitor { protected Stack stack = new Stack(); protected void enter(CtElement e) { @@ -58,7 +60,16 @@ public boolean biScan(Collection elements, Collection firstIt = elements.iterator(), secondIt = others.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { + Collection elementsColl = elements; + Collection othersColl = others; + if (elements instanceof Set) { + if (!(others instanceof Set)) { + return fail(); + } + elementsColl = new TreeSet(elements); + othersColl = new TreeSet(others); + } + for (java.util.Iterator firstIt = elementsColl.iterator(), secondIt = othersColl.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { biScan(firstIt.next(), secondIt.next()); } return isNotEqual; @@ -91,42 +102,6 @@ public boolean biScan(CtElement element, CtElement other) { return isNotEqual; } - public boolean biScan(Object element, Object other) { - if (isNotEqual) { - return isNotEqual; - } - if (element == null) { - if (other != null) { - return fail(); - } - return isNotEqual; - } else if (other == null) { - return fail(); - } - if (element == other) { - return isNotEqual; - } - if (element instanceof Map || other instanceof Map) { - throw new SpoonException("Internal error. Can't bi scan Map."); - } - if (element instanceof CtElement) { - if (!(other instanceof CtElement)) { - return fail(); - } - return biScan((CtElement) element, (CtElement) other); - } - if (element instanceof Collection) { - if (!(other instanceof Collection)) { - return fail(); - } - return biScan((Collection) element, (Collection) other); - } - if (!element.equals(other)) { - return fail(); - } - return isNotEqual; - } - public boolean fail() { isNotEqual = true; return true; diff --git a/src/main/java/spoon/reflect/visitor/CtBiScanner.java b/src/main/java/spoon/reflect/visitor/CtBiScanner.java index f0e2763f736..8f2a3c63f94 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScanner.java @@ -18,13 +18,14 @@ package spoon.reflect.visitor; - /** * This visitor implements a deep-search scan on the model for 2 elements. * * Ensures that all children nodes are visited once, a visit means three method * calls, one call to "enter", one call to "exit" and one call to biScan. * + * This class is generated automatically by the processor {@link spoon.generating.CtBiScannerGenerator}.z + * * Is used by EqualsVisitor. */ public abstract class CtBiScanner implements spoon.reflect.visitor.CtVisitor { @@ -53,7 +54,16 @@ public boolean biScan(java.util.Collection firstIt = elements.iterator(), secondIt = others.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { + java.util.Collection elementsColl = elements; + java.util.Collection othersColl = others; + if (elements instanceof java.util.Set) { + if (!(others instanceof java.util.Set)) { + return fail(); + } + elementsColl = new java.util.TreeSet(elements); + othersColl = new java.util.TreeSet(others); + } + for (java.util.Iterator firstIt = elementsColl.iterator(), secondIt = othersColl.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { biScan(firstIt.next(), secondIt.next()); } return isNotEqual; @@ -85,42 +95,6 @@ public boolean biScan(spoon.reflect.declaration.CtElement element, spoon.reflect return isNotEqual; } - public boolean biScan(java.lang.Object element, java.lang.Object other) { - if (isNotEqual) { - return isNotEqual; - } - if (element == null) { - if (other != null) { - return fail(); - } - return isNotEqual; - } else if (other == null) { - return fail(); - } - if (element == other) { - return isNotEqual; - } - if ((element instanceof java.util.Map) || (other instanceof java.util.Map)) { - throw new spoon.SpoonException("Internal error. Can't bi scan Map."); - } - if (element instanceof spoon.reflect.declaration.CtElement) { - if (!(other instanceof spoon.reflect.declaration.CtElement)) { - return fail(); - } - return biScan(((spoon.reflect.declaration.CtElement) (element)), ((spoon.reflect.declaration.CtElement) (other))); - } - if (element instanceof java.util.Collection) { - if (!(other instanceof java.util.Collection)) { - return fail(); - } - return biScan(((java.util.Collection) (element)), ((java.util.Collection) (other))); - } - if (!(element.equals(other))) { - return fail(); - } - return isNotEqual; - } - public boolean fail() { isNotEqual = true; return true; @@ -474,7 +448,6 @@ public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { enter(literal); biScan(literal.getAnnotations(), other.getAnnotations()); biScan(literal.getType(), other.getType()); - biScan(literal.getValue(), other.getValue()); biScan(literal.getTypeCasts(), other.getTypeCasts()); biScan(literal.getComments(), other.getComments()); exit(literal); diff --git a/src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java similarity index 83% rename from src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java rename to src/main/java/spoon/support/visitor/equals/EqualsChecker.java index 9c42d3aa881..7b68a8e2752 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsCheckerInheritance.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java @@ -19,6 +19,7 @@ import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtBreak; import spoon.reflect.code.CtContinue; +import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtOperatorAssignment; import spoon.reflect.code.CtStatement; import spoon.reflect.code.CtUnaryOperator; @@ -32,7 +33,7 @@ import spoon.reflect.reference.CtReference; import spoon.reflect.visitor.CtInheritanceScanner; -public class EqualsCheckerInheritance extends CtInheritanceScanner { +public class EqualsChecker extends CtInheritanceScanner { private CtElement other; private boolean isNotEqual; @@ -83,10 +84,27 @@ public void scanCtStatement(CtStatement s) { @Override public void scanCtModifiable(CtModifiable m) { final CtModifiable peek = (CtModifiable) this.other; -/* - biScan(m.getVisibility(), other.getVisibility()); - biScan(m.getModifiers(), other.getModifiers()); -*/ + if (m.getVisibility() == null) { + if (peek.getVisibility() != null) { + isNotEqual = true; + return; + } + } else if (peek.getVisibility() == null) { + isNotEqual = true; + return; + } else if (!m.getVisibility().equals(peek.getVisibility())) { + isNotEqual = true; + return; + } + if (m.getModifiers().size() != peek.getModifiers().size()) { + isNotEqual = true; + return; + } + if (!m.getModifiers().containsAll(peek.getModifiers())) { + isNotEqual = true; + return; + } + super.scanCtModifiable(m); } @Override @@ -178,4 +196,22 @@ public void visitCtParameter(CtParameter e) { } super.visitCtParameter(e); } + + @Override + public void visitCtLiteral(CtLiteral e) { + final CtLiteral peek = (CtLiteral) this.other; + if (e.getValue() == null) { + if (peek.getValue() != null) { + isNotEqual = true; + return; + } + } else if (peek.getValue() == null) { + isNotEqual = true; + return; + } else if (!e.getValue().equals(peek.getValue())) { + isNotEqual = true; + return; + } + super.visitCtLiteral(e); + } } diff --git a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java index 22dd7674320..c267b8c5faf 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java @@ -29,7 +29,7 @@ public static boolean equals(spoon.reflect.declaration.CtElement element, spoon. return !(new spoon.support.visitor.equals.EqualsVisitor().biScan(element, other)); } - private final spoon.support.visitor.equals.EqualsCheckerInheritance checker = new spoon.support.visitor.equals.EqualsCheckerInheritance(); + private final spoon.support.visitor.equals.EqualsChecker checker = new spoon.support.visitor.equals.EqualsChecker(); @java.lang.Override protected void enter(spoon.reflect.declaration.CtElement e) { @@ -358,7 +358,6 @@ public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { enter(literal); biScan(literal.getAnnotations(), other.getAnnotations()); biScan(literal.getType(), other.getType()); - biScan(literal.getValue(), other.getValue()); biScan(literal.getTypeCasts(), other.getTypeCasts()); exit(literal); } From 68d8ba6bf09f64990d24887ec45a2928bbf75edf Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Mon, 30 May 2016 10:21:27 +0200 Subject: [PATCH 4/4] refactor: Put CtBiScannerDef and EqualsVisitor below CtAbstractBiScanner. --- .../generating/CtBiScannerGenerator.java | 4 +- .../generating/EqualsVisitorGenerator.java | 6 +- .../equals/EqualsVisitorTemplate.java | 4 +- .../scanner/CtBiScannerTemplate.java | 81 +---------------- .../reflect/visitor/CtAbstractBiScanner.java | 91 +++++++++++++++++++ ...BiScanner.java => CtBiScannerDefault.java} | 76 +--------------- .../support/visitor/equals/EqualsChecker.java | 50 +++++++++- .../support/visitor/equals/EqualsVisitor.java | 2 +- .../testing/AbstractCtElementAssert.java | 2 +- .../spoon/reflect/visitor/CtScannerTest.java | 9 +- .../resources/expected/AddFieldAtTop.java | 7 +- 11 files changed, 160 insertions(+), 172 deletions(-) create mode 100644 src/main/java/spoon/reflect/visitor/CtAbstractBiScanner.java rename src/main/java/spoon/reflect/visitor/{CtBiScanner.java => CtBiScannerDefault.java} (94%) diff --git a/src/main/java/spoon/generating/CtBiScannerGenerator.java b/src/main/java/spoon/generating/CtBiScannerGenerator.java index 89ea6ea1dfc..5d2a2f6b75e 100644 --- a/src/main/java/spoon/generating/CtBiScannerGenerator.java +++ b/src/main/java/spoon/generating/CtBiScannerGenerator.java @@ -101,7 +101,7 @@ public void visitCtMethod(CtMethod element) { private CtClass createBiScanner() { final CtPackage aPackage = getFactory().Package().getOrCreate(TARGET_BISCANNER_PACKAGE); final CtClass target = getFactory().Class().get(GENERATING_BISCANNER); - target.setSimpleName("CtBiScanner"); + target.setSimpleName("CtBiScannerDefault"); target.addModifier(ModifierKind.PUBLIC); aPackage.addType(target); final List references = target.getReferences(new ReferenceFilter() { @@ -116,7 +116,7 @@ public Class getType() { } }); for (CtTypeReference reference : references) { - reference.setSimpleName("CtBiScanner"); + reference.setSimpleName("CtBiScannerDefault"); reference.setPackage(aPackage.getReference()); } return target; diff --git a/src/main/java/spoon/generating/EqualsVisitorGenerator.java b/src/main/java/spoon/generating/EqualsVisitorGenerator.java index 11579e6fa69..cc3dd3f387a 100644 --- a/src/main/java/spoon/generating/EqualsVisitorGenerator.java +++ b/src/main/java/spoon/generating/EqualsVisitorGenerator.java @@ -25,7 +25,8 @@ import spoon.reflect.declaration.ModifierKind; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; -import spoon.reflect.visitor.CtBiScanner; +import spoon.reflect.visitor.CtAbstractBiScanner; +import spoon.reflect.visitor.CtBiScannerDefault; import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.ReferenceFilter; import spoon.support.visitor.equals.IgnoredByEquals; @@ -65,7 +66,7 @@ public void visitCtMethod(CtMethod element) { target.addMethod(clone); } - }.scan(getFactory().Class().get(CtBiScanner.class)); + }.scan(getFactory().Class().get(CtBiScannerDefault.class)); } private CtClass createEqualsVisitor() { @@ -73,6 +74,7 @@ private CtClass createEqualsVisitor() { final CtClass target = getFactory().Class().get(GENERATING_EQUALS); target.setSimpleName("EqualsVisitor"); target.addModifier(ModifierKind.PUBLIC); + target.setSuperclass(getFactory().Type().createReference(CtAbstractBiScanner.class)); aPackage.addType(target); final List references = target.getReferences(new ReferenceFilter() { @Override diff --git a/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java b/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java index 2b8c8f2bbfe..1042de67cb1 100644 --- a/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java +++ b/src/main/java/spoon/generating/equals/EqualsVisitorTemplate.java @@ -17,7 +17,7 @@ package spoon.generating.equals; import spoon.reflect.declaration.CtElement; -import spoon.reflect.visitor.CtBiScanner; +import spoon.reflect.visitor.CtBiScannerDefault; import spoon.support.visitor.equals.EqualsChecker; /** @@ -25,7 +25,7 @@ * * This class is generated automatically by the processor {@link spoon.generating.EqualsVisitorGenerator}. */ -class EqualsVisitorTemplate extends CtBiScanner { +class EqualsVisitorTemplate extends CtBiScannerDefault { public static boolean equals(CtElement element, CtElement other) { return !new EqualsVisitorTemplate().biScan(element, other); } diff --git a/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java b/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java index f31f25faba5..f5b71c35505 100644 --- a/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java +++ b/src/main/java/spoon/generating/scanner/CtBiScannerTemplate.java @@ -16,13 +16,7 @@ */ package spoon.generating.scanner; -import spoon.reflect.declaration.CtElement; -import spoon.reflect.visitor.CtVisitor; - -import java.util.Collection; -import java.util.Set; -import java.util.Stack; -import java.util.TreeSet; +import spoon.reflect.visitor.CtAbstractBiScanner; /** * This visitor implements a deep-search scan on the model for 2 elements. @@ -34,76 +28,5 @@ * * Is used by EqualsVisitor. */ -abstract class CtBiScannerTemplate implements CtVisitor { - protected Stack stack = new Stack(); - - protected void enter(CtElement e) { - } - - protected void exit(CtElement e) { - } - - protected boolean isNotEqual = false; - - public boolean biScan(Collection elements, Collection others) { - if (isNotEqual) { - return isNotEqual; - } - if (elements == null) { - if (others != null) { - return fail(); - } - return isNotEqual; - } else if (others == null) { - return fail(); - } - if ((elements.size()) != (others.size())) { - return fail(); - } - Collection elementsColl = elements; - Collection othersColl = others; - if (elements instanceof Set) { - if (!(others instanceof Set)) { - return fail(); - } - elementsColl = new TreeSet(elements); - othersColl = new TreeSet(others); - } - for (java.util.Iterator firstIt = elementsColl.iterator(), secondIt = othersColl.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { - biScan(firstIt.next(), secondIt.next()); - } - return isNotEqual; - } - - public boolean biScan(CtElement element, CtElement other) { - if (isNotEqual) { - return isNotEqual; - } - if (element == null) { - if (other != null) { - return fail(); - } - return isNotEqual; - } else if (other == null) { - return fail(); - } - if (element == other) { - return isNotEqual; - } - - stack.push(other); - try { - element.accept(this); - } catch (java.lang.ClassCastException e) { - return fail(); - } finally { - stack.pop(); - } - return isNotEqual; - } - - public boolean fail() { - isNotEqual = true; - return true; - } +abstract class CtBiScannerTemplate extends CtAbstractBiScanner { } diff --git a/src/main/java/spoon/reflect/visitor/CtAbstractBiScanner.java b/src/main/java/spoon/reflect/visitor/CtAbstractBiScanner.java new file mode 100644 index 00000000000..45a7c4e331f --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/CtAbstractBiScanner.java @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2006-2015 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.reflect.visitor; + +import spoon.reflect.declaration.CtElement; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Stack; + +/** + * This abstract bi scanner class declares all scan methods useful for CtBiScannerDefault + */ +public abstract class CtAbstractBiScanner implements CtVisitor { + protected Stack stack = new Stack(); + + protected void enter(CtElement e) { + } + + protected void exit(CtElement e) { + } + + protected boolean isNotEqual = false; + + public boolean biScan(Collection elements, Collection others) { + if (isNotEqual) { + return isNotEqual; + } + if (elements == null) { + if (others != null) { + return fail(); + } + return isNotEqual; + } else if (others == null) { + return fail(); + } + if ((elements.size()) != (others.size())) { + return fail(); + } + for (Iterator firstIt = elements.iterator(), secondIt = others.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { + biScan(firstIt.next(), secondIt.next()); + } + return isNotEqual; + } + + public boolean biScan(CtElement element, CtElement other) { + if (isNotEqual) { + return isNotEqual; + } + if (element == null) { + if (other != null) { + return fail(); + } + return isNotEqual; + } else if (other == null) { + return fail(); + } + if (element == other) { + return isNotEqual; + } + + stack.push(other); + try { + element.accept(this); + } catch (java.lang.ClassCastException e) { + return fail(); + } finally { + stack.pop(); + } + return isNotEqual; + } + + public boolean fail() { + isNotEqual = true; + return true; + } +} diff --git a/src/main/java/spoon/reflect/visitor/CtBiScanner.java b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java similarity index 94% rename from src/main/java/spoon/reflect/visitor/CtBiScanner.java rename to src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java index 8f2a3c63f94..01487099f53 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java @@ -18,88 +18,18 @@ package spoon.reflect.visitor; + /** * This visitor implements a deep-search scan on the model for 2 elements. * * Ensures that all children nodes are visited once, a visit means three method * calls, one call to "enter", one call to "exit" and one call to biScan. * - * This class is generated automatically by the processor {@link spoon.generating.CtBiScannerGenerator}.z + * This class is generated automatically by the processor {@link spoon.generating.CtBiScannerGenerator}. * * Is used by EqualsVisitor. */ -public abstract class CtBiScanner implements spoon.reflect.visitor.CtVisitor { - protected java.util.Stack stack = new java.util.Stack(); - - protected void enter(spoon.reflect.declaration.CtElement e) { - } - - protected void exit(spoon.reflect.declaration.CtElement e) { - } - - protected boolean isNotEqual = false; - - public boolean biScan(java.util.Collection elements, java.util.Collection others) { - if (isNotEqual) { - return isNotEqual; - } - if (elements == null) { - if (others != null) { - return fail(); - } - return isNotEqual; - } else if (others == null) { - return fail(); - } - if ((elements.size()) != (others.size())) { - return fail(); - } - java.util.Collection elementsColl = elements; - java.util.Collection othersColl = others; - if (elements instanceof java.util.Set) { - if (!(others instanceof java.util.Set)) { - return fail(); - } - elementsColl = new java.util.TreeSet(elements); - othersColl = new java.util.TreeSet(others); - } - for (java.util.Iterator firstIt = elementsColl.iterator(), secondIt = othersColl.iterator(); (firstIt.hasNext()) && (secondIt.hasNext());) { - biScan(firstIt.next(), secondIt.next()); - } - return isNotEqual; - } - - public boolean biScan(spoon.reflect.declaration.CtElement element, spoon.reflect.declaration.CtElement other) { - if (isNotEqual) { - return isNotEqual; - } - if (element == null) { - if (other != null) { - return fail(); - } - return isNotEqual; - } else if (other == null) { - return fail(); - } - if (element == other) { - return isNotEqual; - } - stack.push(other); - try { - element.accept(spoon.reflect.visitor.CtBiScanner.this); - } catch (java.lang.ClassCastException e) { - return fail(); - } finally { - stack.pop(); - } - return isNotEqual; - } - - public boolean fail() { - isNotEqual = true; - return true; - } - +public abstract class CtBiScannerDefault extends spoon.reflect.visitor.CtAbstractBiScanner { public void visitCtAnnotation(final spoon.reflect.declaration.CtAnnotation annotation) { spoon.reflect.declaration.CtAnnotation other = ((spoon.reflect.declaration.CtAnnotation) (stack.peek())); enter(annotation); diff --git a/src/main/java/spoon/support/visitor/equals/EqualsChecker.java b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java index 7b68a8e2752..538d43dcc8d 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsChecker.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java @@ -110,7 +110,15 @@ public void scanCtModifiable(CtModifiable m) { @Override public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { final CtOperatorAssignment peek = (CtOperatorAssignment) this.other; - if (!assignment.getKind().equals(peek.getKind())) { + if (assignment.getKind() == null) { + if (peek.getKind() != null) { + isNotEqual = true; + return; + } + } else if (peek.getKind() == null) { + isNotEqual = true; + return; + } else if (!assignment.getKind().equals(peek.getKind())) { isNotEqual = true; return; } @@ -120,7 +128,15 @@ public void visitCtOperatorAssignment(CtOperatorAssignment void visitCtBinaryOperator(CtBinaryOperator e) { final CtBinaryOperator peek = (CtBinaryOperator) this.other; - if (!e.getKind().equals(peek.getKind())) { + if (e.getKind() == null) { + if (peek.getKind() != null) { + isNotEqual = true; + return; + } + } else if (peek.getKind() == null) { + isNotEqual = true; + return; + } else if (!e.getKind().equals(peek.getKind())) { isNotEqual = true; return; } @@ -130,7 +146,15 @@ public void visitCtBinaryOperator(CtBinaryOperator e) { @Override public void visitCtUnaryOperator(CtUnaryOperator e) { final CtUnaryOperator peek = (CtUnaryOperator) this.other; - if (!e.getKind().equals(peek.getKind())) { + if (e.getKind() == null) { + if (peek.getKind() != null) { + isNotEqual = true; + return; + } + } else if (peek.getKind() == null) { + isNotEqual = true; + return; + } else if (!e.getKind().equals(peek.getKind())) { isNotEqual = true; return; } @@ -150,7 +174,15 @@ public void visitCtArrayTypeReference(CtArrayTypeReference e) { @Override public void visitCtBreak(CtBreak e) { final CtBreak peek = (CtBreak) this.other; - if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + if (e.getTargetLabel() == null) { + if (peek.getTargetLabel() != null) { + isNotEqual = true; + return; + } + } else if (peek.getTargetLabel() == null) { + isNotEqual = true; + return; + } else if (!e.getTargetLabel().equals(peek.getTargetLabel())) { isNotEqual = true; return; } @@ -160,7 +192,15 @@ public void visitCtBreak(CtBreak e) { @Override public void visitCtContinue(CtContinue e) { final CtContinue peek = (CtContinue) this.other; - if (!e.getTargetLabel().equals(peek.getTargetLabel())) { + if (e.getTargetLabel() == null) { + if (peek.getTargetLabel() != null) { + isNotEqual = true; + return; + } + } else if (peek.getTargetLabel() == null) { + isNotEqual = true; + return; + } else if (!e.getTargetLabel().equals(peek.getTargetLabel())) { isNotEqual = true; return; } diff --git a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java index c267b8c5faf..08818d17f3a 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java @@ -24,7 +24,7 @@ * * This class is generated automatically by the processor {@link spoon.generating.EqualsVisitorGenerator}. */ -public class EqualsVisitor extends spoon.reflect.visitor.CtBiScanner { +public class EqualsVisitor extends spoon.reflect.visitor.CtAbstractBiScanner { public static boolean equals(spoon.reflect.declaration.CtElement element, spoon.reflect.declaration.CtElement other) { return !(new spoon.support.visitor.equals.EqualsVisitor().biScan(element, other)); } diff --git a/src/main/java/spoon/testing/AbstractCtElementAssert.java b/src/main/java/spoon/testing/AbstractCtElementAssert.java index c7207179c8e..8954904c12b 100644 --- a/src/main/java/spoon/testing/AbstractCtElementAssert.java +++ b/src/main/java/spoon/testing/AbstractCtElementAssert.java @@ -40,7 +40,7 @@ public T isEqualTo(CtElement expected) { process(actual.getFactory(), processors); - if (!actual.toString().equals(expected.toString())) { + if (!actual.equals(expected)) { throw new AssertionError(String.format("%1$s and %2$s aren't equals.", actual.getSignature(), expected.getSignature())); } return this.myself; diff --git a/src/test/java/spoon/reflect/visitor/CtScannerTest.java b/src/test/java/spoon/reflect/visitor/CtScannerTest.java index 111b8bd895f..97d4bf0d16d 100644 --- a/src/test/java/spoon/reflect/visitor/CtScannerTest.java +++ b/src/test/java/spoon/reflect/visitor/CtScannerTest.java @@ -96,11 +96,11 @@ public void testGenerateCtBiScanner() throws Exception { launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtScanner.java"); launcher.addInputResource("./src/main/java/spoon/generating/scanner/"); launcher.addProcessor(new CtBiScannerGenerator()); - launcher.setOutputFilter(new RegexFilter("spoon.reflect.visitor.CtBiScanner")); + launcher.setOutputFilter(new RegexFilter("spoon.reflect.visitor.CtBiScannerDefault")); launcher.run(); - assertThat(build(new File("./src/main/java/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)) - .isEqualTo(build(new File("./target/generated/spoon/reflect/visitor/CtBiScanner.java")).Class().get(CtBiScanner.class)); + assertThat(build(new File("./src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java")).Class().get(CtBiScannerDefault.class)) + .isEqualTo(build(new File("./target/generated/spoon/reflect/visitor/CtBiScannerDefault.java")).Class().get(CtBiScannerDefault.class)); } @Test @@ -116,7 +116,8 @@ public void testGenerateEqualsVisitor() throws Exception { launcher.addInputResource("./src/main/java/spoon/reflect/reference"); launcher.addInputResource("./src/main/java/spoon/reflect/internal"); // Utils. - launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtBiScanner.java"); + launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtAbstractBiScanner.java"); + launcher.addInputResource("./src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java"); launcher.addInputResource("./src/main/java/spoon/generating/equals/"); launcher.addProcessor(new EqualsVisitorGenerator()); launcher.setOutputFilter(new RegexFilter("spoon.support.visitor.equals.EqualsVisitor")); diff --git a/src/test/resources/expected/AddFieldAtTop.java b/src/test/resources/expected/AddFieldAtTop.java index 0da51b43971..07c02356b5a 100644 --- a/src/test/resources/expected/AddFieldAtTop.java +++ b/src/test/resources/expected/AddFieldAtTop.java @@ -1,13 +1,14 @@ public class AddFieldAtTop { - java.lang.String generated; - - java.lang.String generated2; static { } int i; + java.lang.String generated; + + java.lang.String generated2; + void m() { } } \ No newline at end of file