diff options
author | Michael Hoffmann <datoma@users.noreply.github.com> | 2017-10-17 22:58:04 +0200 |
---|---|---|
committer | Evgeny Mandrikov <Godin@users.noreply.github.com> | 2017-10-17 22:58:04 +0200 |
commit | ec6287a6b947b8e91a1c697aebdb157bbfab564b (patch) | |
tree | 0305fc76f722632950eba1fc334eb2222d11e798 | |
parent | 88d7b01d00451a1351aa7eec4783860844b58c29 (diff) | |
download | jacoco-ec6287a6b947b8e91a1c697aebdb157bbfab564b.tar.gz |
Add filter for methods annotated with @groovy.transform.Generated (#610)
6 files changed, 205 insertions, 20 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java new file mode 100644 index 00000000..4630762a --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import org.jacoco.core.internal.instr.InstrSupport; +import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.MethodNode; + +public class GroovyGeneratedFilterTest implements IFilterOutput { + + private final IFilter filter = new GroovyGeneratedFilter(); + + private AbstractInsnNode fromInclusive; + private AbstractInsnNode toInclusive; + + @Test + public void testNoAnnotations() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "hashCode", "()I", null, null); + + m.visitInsn(Opcodes.ICONST_0); + m.visitInsn(Opcodes.IRETURN); + + filter.filter("Foo", "java/lang/Object", m, this); + + assertNull(fromInclusive); + assertNull(toInclusive); + } + + @Test + public void testOtherAnnotation() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "hashCode", "()I", null, null); + m.visitAnnotation("Lother/Annotation;", true); + + m.visitInsn(Opcodes.ICONST_0); + m.visitInsn(Opcodes.IRETURN); + + filter.filter("Foo", "java/lang/Object", m, this); + + assertNull(fromInclusive); + assertNull(toInclusive); + } + + @Test + public void testGroovyGeneratedAnnotation() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "hashCode", "()I", null, null); + m.visitAnnotation("Lgroovy/transform/Generated;", true); + + m.visitInsn(Opcodes.ICONST_0); + m.visitInsn(Opcodes.IRETURN); + + filter.filter("Foo", "java/lang/Object", m, this); + + assertEquals(m.instructions.getFirst(), fromInclusive); + assertEquals(m.instructions.getLast(), toInclusive); + } + + public void ignore(final AbstractInsnNode fromInclusive, + final AbstractInsnNode toInclusive) { + assertNull(this.fromInclusive); + this.fromInclusive = fromInclusive; + this.toInclusive = toInclusive; + } + + public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) { + fail(); + } + +} diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java new file mode 100644 index 00000000..75e33093 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import java.util.List; + +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters annotated methods. + */ +abstract class AbstractAnnotatedMethodFilter implements IFilter { + private final String descType; + + /** + * Configures a new filter instance. + * + * @param annotationType + * VM type of the annotation + */ + protected AbstractAnnotatedMethodFilter(final String annotationType) { + this.descType = "L" + annotationType + ";"; + } + + public void filter(final String className, final String superClassName, + final MethodNode methodNode, final IFilterOutput output) { + if (hasAnnotation(methodNode)) { + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + } + + private boolean hasAnnotation(final MethodNode methodNode) { + final List<AnnotationNode> annotations = getAnnotations(methodNode); + if (annotations != null) { + for (final AnnotationNode annotation : annotations) { + if (descType.equals(annotation.desc)) { + return true; + } + } + } + return false; + } + + /** + * Retrieves the annotations to search from a method. Depending on the + * retention of the annotation this is either + * <code>visibleAnnotations</code> or <code>invisibleAnnotations</code>. + * + * @param methodNode + * method to retrieve annotations from + * @return list of annotations + */ + abstract List<AnnotationNode> getAnnotations(final MethodNode methodNode); + +} diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java index e2c26d92..4b2a64a9 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java @@ -30,11 +30,12 @@ public final class Filters implements IFilter { new SyntheticFilter(), new SynchronizedFilter(), new TryWithResourcesJavacFilter(), new TryWithResourcesEcjFilter(), new PrivateEmptyNoArgConstructorFilter(), - new StringSwitchJavacFilter(), new LombokGeneratedFilter()); + new StringSwitchJavacFilter(), new LombokGeneratedFilter(), + new GroovyGeneratedFilter()); private final IFilter[] filters; - private Filters(IFilter... filters) { + private Filters(final IFilter... filters) { this.filters = filters; } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java new file mode 100644 index 00000000..353868d5 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import java.util.List; + +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters methods annotated with <code>@groovy.transform.Generated</code>. + */ +public final class GroovyGeneratedFilter extends AbstractAnnotatedMethodFilter { + + /** + * New filter. + */ + public GroovyGeneratedFilter() { + super("groovy/transform/Generated"); + } + + @Override + List<AnnotationNode> getAnnotations(final MethodNode methodNode) { + return methodNode.visibleAnnotations; + } + +} diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java index 98575e80..62021ae7 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java @@ -19,26 +19,18 @@ import org.objectweb.asm.tree.MethodNode; /** * Filters methods annotated with <code>@lombok.Generated</code>. */ -public final class LombokGeneratedFilter implements IFilter { +public final class LombokGeneratedFilter extends AbstractAnnotatedMethodFilter { - public void filter(final String className, final String superClassName, - final MethodNode methodNode, final IFilterOutput output) { - if (hasLombokGeneratedAnnotation(methodNode)) { - output.ignore(methodNode.instructions.getFirst(), - methodNode.instructions.getLast()); - } + /** + * New filter. + */ + public LombokGeneratedFilter() { + super("lombok/Generated"); } - private boolean hasLombokGeneratedAnnotation(final MethodNode methodNode) { - final List<AnnotationNode> runtimeInvisibleAnnotations = methodNode.invisibleAnnotations; - if (runtimeInvisibleAnnotations != null) { - for (final AnnotationNode annotation : runtimeInvisibleAnnotations) { - if ("Llombok/Generated;".equals(annotation.desc)) { - return true; - } - } - } - return false; + @Override + List<AnnotationNode> getAnnotations(final MethodNode methodNode) { + return methodNode.invisibleAnnotations; } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 5ae14dd5..b9e61a12 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -35,8 +35,12 @@ try-with-resources statement (GitHub <a href="https://github.com/jacoco/jacoco/issues/500">#500</a>).</li> <li>Exclude from a report methods which are annotated with <code>@lombok.Generated</code>. - Initial analysis and contribution by RĂ¼diger zu Dohna. + Initial analysis and contribution by RĂ¼diger zu Dohna (GitHub <a href="https://github.com/jacoco/jacoco/issues/513">#513</a>).</li> + <li>Exclude from a report methods which are annotated with + <code>@groovy.transform.Generated</code> to better integrate with Groovy + >= 2.5.0. Thanks to Andres Almiray for adding the annotation to Groovy + (GitHub <a href="https://github.com/jacoco/jacoco/issues/610">#610</a>).</li> <li>Exclude from a report private empty constructors that do not have arguments (GitHub <a href="https://github.com/jacoco/jacoco/issues/529">#529</a>).</li> <li>Exclude from a report a part of bytecode that javac generates for a |