From 3ae379f211844f608d58bf7fbdd5b033dc7fefcb Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Tue, 28 Jun 2016 16:23:37 +0200 Subject: [PATCH] fix(clone): Scan declaring executable of CtParameterRef. Closes #729 --- .../reflect/visitor/CtBiScannerDefault.java | 1 + .../java/spoon/reflect/visitor/CtScanner.java | 1 + .../support/visitor/clone/CloneVisitor.java | 1 + .../support/visitor/equals/EqualsVisitor.java | 19 ++++++------ .../visitor/replace/ReplacementVisitor.java | 16 +++++++++- .../ExecutableReferenceGenericTest.java | 29 ++++++++++++++++--- .../test/reference/VariableAccessTest.java | 23 +++++++++++++++ src/test/resources/noclasspath/Foo2.java | 12 ++++++++ 8 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 src/test/resources/noclasspath/Foo2.java diff --git a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java index 182dd3ba6d4..4b0c0b56618 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java @@ -524,6 +524,7 @@ public void visitCtParameterReference(final spoon.reflect.reference.CtParame enter(reference); biScan(reference.getType(), other.getType()); biScan(reference.getAnnotations(), other.getAnnotations()); + biScan(reference.getDeclaringExecutable(), other.getDeclaringExecutable()); exit(reference); } diff --git a/src/main/java/spoon/reflect/visitor/CtScanner.java b/src/main/java/spoon/reflect/visitor/CtScanner.java index 78e199a3325..1ef5b316940 100644 --- a/src/main/java/spoon/reflect/visitor/CtScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtScanner.java @@ -625,6 +625,7 @@ public void visitCtParameterReference(final CtParameterReference referenc enter(reference); scan(reference.getType()); scan(reference.getAnnotations()); + scan(reference.getDeclaringExecutable()); exit(reference); } diff --git a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java index 3b3800d0354..201203f62a7 100644 --- a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java +++ b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java @@ -527,6 +527,7 @@ public void visitCtParameterReference(final spoon.reflect.reference.CtParame spoon.reflect.reference.CtParameterReference aCtParameterReference = spoon.support.visitor.clone.CloneBuilder.build(this.builder, reference, reference.getFactory().Core().createParameterReference()); aCtParameterReference.setType(spoon.support.visitor.equals.CloneHelper.clone(reference.getType())); aCtParameterReference.setAnnotations(spoon.support.visitor.equals.CloneHelper.clone(reference.getAnnotations())); + aCtParameterReference.setDeclaringExecutable(spoon.support.visitor.equals.CloneHelper.clone(reference.getDeclaringExecutable())); this.other = aCtParameterReference; } diff --git a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java index 8655d5c962e..771b27178ab 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsVisitor.java @@ -31,6 +31,15 @@ public static boolean equals(spoon.reflect.declaration.CtElement element, spoon. private final spoon.support.visitor.equals.EqualsChecker checker = new spoon.support.visitor.equals.EqualsChecker(); + 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); + } + @java.lang.Override protected void enter(spoon.reflect.declaration.CtElement e) { super.enter(e); @@ -41,15 +50,6 @@ protected void enter(spoon.reflect.declaration.CtElement e) { } } - 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); @@ -494,6 +494,7 @@ public void visitCtParameterReference(final spoon.reflect.reference.CtParame enter(reference); biScan(reference.getType(), other.getType()); biScan(reference.getAnnotations(), other.getAnnotations()); + biScan(reference.getDeclaringExecutable(), other.getDeclaringExecutable()); exit(reference); } diff --git a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java index c90a3512b09..2a0acf7f001 100644 --- a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java +++ b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java @@ -714,6 +714,19 @@ public void set(java.util.Set replace) { } } + class CtParameterReferenceDeclaringExecutableReplaceListener implements spoon.generating.replace.ReplaceListener { + private spoon.reflect.reference.CtParameterReference element; + + CtParameterReferenceDeclaringExecutableReplaceListener(spoon.reflect.reference.CtParameterReference element) { + this.element = element; + } + + @java.lang.Override + public void set(spoon.reflect.reference.CtExecutableReference replace) { + this.element.setDeclaringExecutable(replace); + } + } + class CtRHSReceiverAssignmentReplaceListener implements spoon.generating.replace.ReplaceListener { private spoon.reflect.code.CtRHSReceiver element; @@ -1161,7 +1174,7 @@ private void replaceInListIfExis } if (shouldBeDeleted != null) { if ((replace) != null) { - list.set(index, (T) replace); + list.set(index, ((T) (replace))); replace.setParent(shouldBeDeleted.getParent()); } else { list.remove(index); @@ -1536,6 +1549,7 @@ public void visitCtParameter(final spoon.reflect.declaration.CtParameter public void visitCtParameterReference(final spoon.reflect.reference.CtParameterReference reference) { replaceElementIfExist(reference.getType(), new spoon.support.visitor.replace.ReplacementVisitor.CtVariableReferenceTypeReplaceListener(reference)); replaceInListIfExist(reference.getAnnotations(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementAnnotationsReplaceListener(reference)); + replaceElementIfExist(reference.getDeclaringExecutable(), new spoon.support.visitor.replace.ReplacementVisitor.CtParameterReferenceDeclaringExecutableReplaceListener(reference)); } public void visitCtReturn(final spoon.reflect.code.CtReturn returnStatement) { diff --git a/src/test/java/spoon/test/reference/ExecutableReferenceGenericTest.java b/src/test/java/spoon/test/reference/ExecutableReferenceGenericTest.java index d792fb39502..94e955bc7df 100644 --- a/src/test/java/spoon/test/reference/ExecutableReferenceGenericTest.java +++ b/src/test/java/spoon/test/reference/ExecutableReferenceGenericTest.java @@ -5,6 +5,7 @@ import spoon.Launcher; import spoon.compiler.SpoonCompiler; import spoon.compiler.SpoonResourceHelper; +import spoon.reflect.code.CtInvocation; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtConstructor; import spoon.reflect.declaration.CtMethod; @@ -16,6 +17,7 @@ import spoon.reflect.visitor.filter.NameFilter; import spoon.reflect.visitor.filter.ReferenceTypeFilter; +import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertEquals; @@ -70,7 +72,7 @@ public void testReferencesBetweenConstructors() throws Exception { public void testReferencesBetweenConstructorsInOtherClass() throws Exception { final List> constructors = getConstructorsByClass("MyClass2"); final CtConstructor ctConstructor = constructors.get(0); - final List> refConstructors = getCtConstructorsByCtConstructor(ctConstructor); + final List> refConstructors = getCtConstructorsReferencedInCtConstructor(ctConstructor); final CtClass clazz1 = getCtClassByName("MyClass"); final CtConstructor emptyConstructorClass1 = getConstructorsByClass(clazz1.getSimpleName()).get(0); @@ -229,7 +231,7 @@ public boolean matches(CtExecutableReference reference) { } }); - assertEquals(10, refsExecutableClass1.size()); + assertEquals(11, refsExecutableClass1.size()); for (CtExecutableReference ref : refsExecutableClass1) { assertNotNull(ref); if (!ref.toString().equals("java.lang.Object#Object()")) { @@ -255,8 +257,27 @@ public boolean matches(CtConstructor element) { }); } - private List> getCtConstructorsByCtConstructor(CtConstructor emptyConstructor) { - return emptyConstructor.getReferences(new AbstractReferenceFilter>(CtExecutableReference.class) { + private List> getCtConstructorsByCtConstructor(CtConstructor aConstructor) { + if (aConstructor.getBody().getStatements().size() == 0) { + return new ArrayList<>(); + } + if (!(aConstructor.getBody().getStatement(0) instanceof CtInvocation)) { + return new ArrayList<>(); + } + final CtInvocation inv = aConstructor.getBody().getStatement(0); + if (!inv.getExecutable().getSimpleName().equals(CtExecutableReference.CONSTRUCTOR_NAME)) { + return new ArrayList<>(); + } + return inv.getExecutable().getReferences(new AbstractReferenceFilter>(CtExecutableReference.class) { + @Override + public boolean matches(CtExecutableReference reference) { + return reference.isConstructor(); + } + }); + } + + private List> getCtConstructorsReferencedInCtConstructor(CtConstructor aConstructor) { + return aConstructor.getReferences(new AbstractReferenceFilter>(CtExecutableReference.class) { @Override public boolean matches(CtExecutableReference reference) { return reference.isConstructor(); diff --git a/src/test/java/spoon/test/reference/VariableAccessTest.java b/src/test/java/spoon/test/reference/VariableAccessTest.java index f526e5db06e..671a3bfb0d9 100644 --- a/src/test/java/spoon/test/reference/VariableAccessTest.java +++ b/src/test/java/spoon/test/reference/VariableAccessTest.java @@ -1,6 +1,7 @@ package spoon.test.reference; import org.junit.Test; +import spoon.Launcher; import spoon.reflect.code.CtArrayWrite; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtVariableAccess; @@ -8,6 +9,7 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.reference.CtParameterReference; +import spoon.reflect.reference.CtVariableReference; import spoon.reflect.visitor.filter.AbstractReferenceFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.test.reference.testclasses.Pozole; @@ -15,6 +17,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; import static spoon.testing.utils.ModelUtils.build; public class VariableAccessTest { @@ -47,4 +50,24 @@ public void name() throws Exception { assertEquals(expected, ((CtVariableAccess) ctArrayWrite.getTarget()).getVariable().getDeclaration()); } + + @Test + public void testDeclarationOfVariableReference() throws Exception { + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/Foo2.java"); + launcher.getEnvironment().setNoClasspath(true); + launcher.buildModel(); + + launcher.getModel().getElements(new TypeFilter(CtVariableReference.class) { + @Override + public boolean matches(CtVariableReference element) { + try { + element.clone().getDeclaration(); + } catch (NullPointerException e) { + fail("Fail with " + element.getSimpleName() + " declared in " + element.getParent().getSignature()); + } + return super.matches(element); + } + }); + } } diff --git a/src/test/resources/noclasspath/Foo2.java b/src/test/resources/noclasspath/Foo2.java new file mode 100644 index 00000000000..a309f6509c3 --- /dev/null +++ b/src/test/resources/noclasspath/Foo2.java @@ -0,0 +1,12 @@ +class Foo2 { + public void foo() { + JButton b = new JButton(); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + switch (e.getActionCommand()) { + } + } + }); + } +} \ No newline at end of file