Use new filtering API for existing filter of synthetic methods (#511)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
index 9c8e6df..6da24ff 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
@@ -60,34 +60,6 @@
}
@Test
- public void testMethodFilter_NonSynthetic() {
- final MethodProbesVisitor mv = analyzer.visitMethod(0, "foo", "()V",
- null, null);
- mv.visitCode();
- mv.visitInsn(Opcodes.RETURN);
- mv.visitEnd();
- assertEquals(1, coverage.getMethods().size());
- }
-
- @Test
- public void testMethodFilter_Synthetic() {
- final MethodProbesVisitor mv = analyzer.visitMethod(
- Opcodes.ACC_SYNTHETIC, "foo", "()V", null, null);
- assertNull(mv);
- assertTrue(coverage.getMethods().isEmpty());
- }
-
- @Test
- public void testMethodFilter_Lambda() {
- final MethodProbesVisitor mv = analyzer.visitMethod(
- Opcodes.ACC_SYNTHETIC, "lambda$1", "()V", null, null);
- mv.visitCode();
- mv.visitInsn(Opcodes.RETURN);
- mv.visitEnd();
- assertEquals(1, coverage.getMethods().size());
- }
-
- @Test
public void testMethodFilter_EnumValues() {
analyzer.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "Foo", null,
"java/lang/Enum", null);
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java
new file mode 100644
index 0000000..75648dc
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class SyntheticFilterTest implements IFilterOutput {
+
+ private final SyntheticFilter filter = new SyntheticFilter();
+
+ private AbstractInsnNode fromInclusive;
+ private AbstractInsnNode toInclusive;
+
+ @Test
+ public void testNonSynthetic() {
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "name", "()V", null, null);
+ m.visitInsn(Opcodes.NOP);
+
+ filter.filter(m, this);
+
+ assertNull(fromInclusive);
+ assertNull(toInclusive);
+ }
+
+ @Test
+ public void testSynthetic() {
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+ Opcodes.ACC_SYNTHETIC, "name", "()V", null, null);
+ m.visitInsn(Opcodes.NOP);
+
+ filter.filter(m, this);
+
+ assertEquals(m.instructions.getFirst(), fromInclusive);
+ assertEquals(m.instructions.getLast(), toInclusive);
+ }
+
+ @Test
+ public void testLambda() {
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+ Opcodes.ACC_SYNTHETIC, "lambda$1", "()V", null, null);
+ m.visitInsn(Opcodes.NOP);
+
+ filter.filter(m, this);
+
+ assertNull(fromInclusive);
+ assertNull(toInclusive);
+ }
+
+ public void ignore(final AbstractInsnNode fromInclusive,
+ final AbstractInsnNode toInclusive) {
+ assertNull(this.fromInclusive);
+ this.fromInclusive = fromInclusive;
+ this.toInclusive = toInclusive;
+ }
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java
new file mode 100644
index 0000000..a0b54e0
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.filter;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.filter.targets.Synthetic;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.junit.Test;
+
+/**
+ * Test of filtering of synthetic methods.
+ */
+public class SyntheticTest extends ValidationTestBase {
+
+ public SyntheticTest() {
+ super(Synthetic.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+ assertMethodCount(6);
+
+ assertLine("classdef", ICounter.EMPTY);
+ assertLine("field", ICounter.EMPTY);
+
+ assertLine("inner.classdef", ICounter.EMPTY);
+ }
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java
new file mode 100644
index 0000000..4a9adfd
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.filter.targets;
+
+/**
+ * This test target is synthetic methods.
+ */
+public class Synthetic { // $line-classdef$
+
+ private static int counter; // $line-field$
+
+ private Synthetic() {
+ }
+
+ private static class Inner extends Synthetic { // $line-inner.classdef$
+ Inner() {
+ }
+
+ /**
+ * Access to private field of outer class causes creation of synthetic
+ * methods in it. In case of javac those methods refer to the line of
+ * outer class definition, in case of ECJ - to the line of field.
+ */
+ private static void inc() {
+ counter = counter + 2;
+ }
+
+ /**
+ * Difference of return type with overridden method causes creation of
+ * synthetic bridge method in this class. In case of javac this method
+ * refers to the line of inner class definition, in case of EJC - to the
+ * first line of file.
+ */
+ @Override
+ public String get() {
+ return null;
+ }
+ }
+
+ public Object get() {
+ return null;
+ }
+
+ public static void main(String[] args) {
+ Inner.inc();
+ }
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
index ddc1da1..643b599 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
@@ -26,6 +26,8 @@
@Test
public void testCoverageResult() {
+ assertMethodCount(5);
+
assertLine("classdef", ICounter.FULLY_COVERED);
assertLine("customValueOfMethod", ICounter.NOT_COVERED);
assertLine("customValuesMethod", ICounter.NOT_COVERED);
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
index 46a19a5..c8693f9 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
@@ -109,6 +109,11 @@
analyzer.analyzeClass(bytes, data.getName());
}
+ protected void assertMethodCount(final int expectedTotal) {
+ assertEquals(expectedTotal,
+ sourceCoverage.getMethodCounter().getTotalCount());
+ }
+
protected void assertLine(final String tag, final int status) {
final int nr = source.getLineNumber(tag);
final ILine line = sourceCoverage.getLine(nr);
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
index 06e1324..38037be 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
@@ -16,7 +16,6 @@
import org.jacoco.core.internal.flow.MethodProbesVisitor;
import org.jacoco.core.internal.instr.InstrSupport;
import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Opcodes;
/**
* Analyzes the structure of a class.
@@ -64,8 +63,8 @@
InstrSupport.assertNotInstrumented(name, coverage.getName());
- if (isMethodFiltered(coverage.getName(), coverage.getSuperName(),
- access, name, desc)) {
+ if (isMethodFiltered(coverage.getName(), coverage.getSuperName(), name,
+ desc)) {
return null;
}
@@ -88,8 +87,7 @@
*/
// TODO: Use filter hook in future
private boolean isMethodFiltered(final String className,
- final String superClassName, final int access, final String name,
- final String desc) {
+ final String superClassName, final String name, final String desc) {
if ("java/lang/Enum".equals(superClassName)) {
// filter out methods that compiler creates for enums
if ("values".equals(name)
@@ -102,8 +100,7 @@
return true;
}
}
- return (access & Opcodes.ACC_SYNTHETIC) != 0
- && !name.startsWith("lambda$");
+ return false;
}
@Override
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
index 6736aca..a912e33 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
@@ -22,6 +22,7 @@
import org.jacoco.core.internal.analysis.filter.IFilter;
import org.jacoco.core.internal.analysis.filter.IFilterOutput;
import org.jacoco.core.internal.analysis.filter.SynchronizedFilter;
+import org.jacoco.core.internal.analysis.filter.SyntheticFilter;
import org.jacoco.core.internal.flow.IFrame;
import org.jacoco.core.internal.flow.Instruction;
import org.jacoco.core.internal.flow.LabelInfo;
@@ -41,7 +42,7 @@
implements IFilterOutput {
private static final IFilter[] FILTERS = new IFilter[] {
- new SynchronizedFilter() };
+ new SyntheticFilter(), new SynchronizedFilter() };
private final boolean[] probes;
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java
new file mode 100644
index 0000000..540909d
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters synthetic methods unless they represent bodies of lambda expressions.
+ */
+public final class SyntheticFilter implements IFilter {
+
+ public void filter(MethodNode methodNode, IFilterOutput output) {
+ if ((methodNode.access & Opcodes.ACC_SYNTHETIC) != 0
+ && !methodNode.name.startsWith("lambda$")) {
+ output.ignore(methodNode.instructions.getFirst(),
+ methodNode.instructions.getLast());
+ }
+ }
+
+}