aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java83
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java9
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java11
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java5
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java12
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java3
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java75
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java48
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java11
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java2
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java11
16 files changed, 265 insertions, 30 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
index c746131e..90f4c05b 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
@@ -17,6 +17,9 @@ import java.util.ArrayList;
import org.jacoco.core.analysis.ILine;
import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.internal.analysis.filter.Filters;
+import org.jacoco.core.internal.analysis.filter.IFilter;
+import org.jacoco.core.internal.analysis.filter.IFilterOutput;
import org.jacoco.core.internal.flow.IProbeIdGenerator;
import org.jacoco.core.internal.flow.LabelFlowAnalyzer;
import org.jacoco.core.internal.flow.MethodProbesAdapter;
@@ -24,6 +27,7 @@ import org.junit.Before;
import org.junit.Test;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.util.CheckMethodAdapter;
@@ -638,15 +642,90 @@ public class MethodAnalyzerTest implements IProbeIdGenerator {
assertLine(1004, 0, 1, 0, 0);
}
+ // === Scenario: try/finally ===
+
+ private void createTryFinally() {
+ final Label l0 = new Label();
+ final Label l1 = new Label();
+ final Label l2 = new Label();
+ final Label l3 = new Label();
+
+ method.visitTryCatchBlock(l0, l2, l2, null);
+
+ method.visitLabel(l0);
+ method.visitLineNumber(1001, l0);
+
+ method.visitJumpInsn(Opcodes.IFEQ, l1);
+ // probe[0]
+ method.visitInsn(Opcodes.RETURN);
+ method.visitLabel(l1);
+ // probe[1]
+ method.visitInsn(Opcodes.RETURN);
+
+ method.visitLabel(l2);
+ method.visitJumpInsn(Opcodes.IFEQ, l3);
+ // probe[2]
+ method.visitInsn(Opcodes.RETURN);
+ method.visitLabel(l3);
+ // probe[3]
+ method.visitInsn(Opcodes.RETURN);
+ }
+
+ @Test
+ public void testTryFinallyWithoutFilter() {
+ createTryFinally();
+ probes[0] = true;
+ probes[3] = true;
+ runMethodAnalzer();
+ assertEquals(4, nextProbeId);
+
+ assertLine(1001, 2, 4, 2, 2);
+ }
+
+ private static final IFilter TRY_FINALLY_FILTER = new IFilter() {
+ public void filter(final String className, final String superClassName,
+ final MethodNode methodNode, final IFilterOutput output) {
+ final AbstractInsnNode i1 = methodNode.instructions.get(2);
+ final AbstractInsnNode i2 = methodNode.instructions.get(7);
+ assertEquals(Opcodes.IFEQ, i1.getOpcode());
+ assertEquals(Opcodes.IFEQ, i2.getOpcode());
+ output.merge(i1, i2);
+ // Merging of already merged instructions won't change result:
+ output.merge(i1, i2);
+ }
+ };
+
+ @Test
+ public void testTryFinallyMergeSameBranch() {
+ createTryFinally();
+ probes[0] = true;
+ probes[2] = true;
+ runMethodAnalzer(TRY_FINALLY_FILTER);
+ assertLine(1001, 2, 3, 1, 1);
+ }
+
+ @Test
+ public void testTryFinallyMergeDifferentBranches() {
+ createTryFinally();
+ probes[0] = true;
+ probes[3] = true;
+ runMethodAnalzer(TRY_FINALLY_FILTER);
+ assertLine(1001, 2, 3, 0, 2);
+ }
+
private void runMethodAnalzer() {
+ runMethodAnalzer(Filters.NONE);
+ }
+
+ private void runMethodAnalzer(IFilter filter) {
LabelFlowAnalyzer.markLabels(method);
final MethodAnalyzer analyzer = new MethodAnalyzer("Foo",
- "java/lang/Object", "doit", "()V", null, probes);
+ "java/lang/Object", "doit", "()V", null, probes, filter);
final MethodProbesAdapter probesAdapter = new MethodProbesAdapter(
analyzer, this);
// note that CheckMethodAdapter verifies that this test does not violate
// contracts of ASM API
- method.accept(new CheckMethodAdapter(probesAdapter));
+ analyzer.accept(method, new CheckMethodAdapter(probesAdapter));
result = analyzer.getCoverage();
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
index 149990f5..a46a0d64 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
@@ -13,6 +13,7 @@ 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;
@@ -94,4 +95,8 @@ public class EnumFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java
index 8fae5cc3..e68b3a3c 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java
@@ -13,6 +13,7 @@ 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;
@@ -78,4 +79,8 @@ public class LombokGeneratedFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
index 90262081..36c57ecb 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
@@ -11,14 +11,15 @@
*******************************************************************************/
package org.jacoco.core.internal.analysis.filter;
+import static org.junit.Assert.assertEquals;
+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;
-import static org.junit.Assert.assertEquals;
-
public class PrivateEmptyNoArgConstructorFilterTest implements IFilterOutput {
private final IFilter filter = new PrivateEmptyNoArgConstructorFilter();
@@ -48,4 +49,8 @@ public class PrivateEmptyNoArgConstructorFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
index 5a7cdefb..96683961 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
@@ -11,6 +11,10 @@
*******************************************************************************/
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.Label;
@@ -18,9 +22,6 @@ 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 StringSwitchJavacFilterTest implements IFilterOutput {
private final IFilter filter = new StringSwitchJavacFilter();
@@ -152,4 +153,8 @@ public class StringSwitchJavacFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
index b0f5d1b0..a67eaa5f 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
@@ -13,6 +13,7 @@ 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;
@@ -163,4 +164,8 @@ public class SynchronizedFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
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
index 319caef5..b8a6e9dd 100644
--- 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
@@ -13,6 +13,7 @@ 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;
@@ -70,4 +71,8 @@ public class SyntheticFilterTest implements IFilterOutput {
this.toInclusive = toInclusive;
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
index d3720505..57e9145b 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
@@ -12,6 +12,7 @@
package org.jacoco.core.internal.analysis.filter;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
@@ -621,4 +622,8 @@ public class TryWithResourcesEcjFilterTest implements IFilterOutput {
this.to.add(to);
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
index 26b4cfe1..a19cfe2c 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
@@ -12,6 +12,7 @@
package org.jacoco.core.internal.analysis.filter;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
@@ -811,4 +812,8 @@ public class TryWithResourcesJavacFilterTest implements IFilterOutput {
this.to.add(to);
}
+ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
+ fail();
+ }
+
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java
index a6fb15e8..a6a7ee6d 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java
@@ -93,6 +93,18 @@ public class InstructionTest {
}
@Test
+ public void merge_should_add_covered_branches_from_another_instruction() {
+ final Instruction i1 = new Instruction(new InsnNode(Opcodes.NOP), 123);
+ i1.setCovered(0);
+ final Instruction i2 = new Instruction(new InsnNode(Opcodes.NOP), 123);
+ i2.setCovered(1);
+ i1.merge(i2);
+ assertEquals("{0, 1}", i1.toString());
+ assertEquals(2, i1.getCoveredBranches());
+ assertEquals("{1}", i2.toString());
+ }
+
+ @Test
public void testSetCoveredOnLongSequence() {
final Instruction first = new Instruction(new InsnNode(Opcodes.NOP), 0);
Instruction next = first;
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 fa3517b6..69a10e7e 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
@@ -12,6 +12,7 @@
package org.jacoco.core.internal.analysis;
import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.internal.analysis.filter.Filters;
import org.jacoco.core.internal.flow.ClassProbesVisitor;
import org.jacoco.core.internal.flow.MethodProbesVisitor;
import org.jacoco.core.internal.instr.InstrSupport;
@@ -65,7 +66,7 @@ public class ClassAnalyzer extends ClassProbesVisitor {
return new MethodAnalyzer(coverage.getName(), coverage.getSuperName(),
stringPool.get(name), stringPool.get(desc),
- stringPool.get(signature), probes) {
+ stringPool.get(signature), probes, Filters.ALL) {
@Override
public void visitEnd() {
super.visitEnd();
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 e216bb77..0be47158 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
@@ -12,23 +12,17 @@
package org.jacoco.core.internal.analysis;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.analysis.ISourceNode;
-import org.jacoco.core.internal.analysis.filter.EnumFilter;
import org.jacoco.core.internal.analysis.filter.IFilter;
import org.jacoco.core.internal.analysis.filter.IFilterOutput;
-import org.jacoco.core.internal.analysis.filter.LombokGeneratedFilter;
-import org.jacoco.core.internal.analysis.filter.PrivateEmptyNoArgConstructorFilter;
-import org.jacoco.core.internal.analysis.filter.StringSwitchJavacFilter;
-import org.jacoco.core.internal.analysis.filter.SynchronizedFilter;
-import org.jacoco.core.internal.analysis.filter.SyntheticFilter;
-import org.jacoco.core.internal.analysis.filter.TryWithResourcesEcjFilter;
-import org.jacoco.core.internal.analysis.filter.TryWithResourcesJavacFilter;
import org.jacoco.core.internal.flow.IFrame;
import org.jacoco.core.internal.flow.Instruction;
import org.jacoco.core.internal.flow.LabelInfo;
@@ -47,18 +41,14 @@ import org.objectweb.asm.tree.TryCatchBlockNode;
public class MethodAnalyzer extends MethodProbesVisitor
implements IFilterOutput {
- private static final IFilter[] FILTERS = new IFilter[] { new EnumFilter(),
- new SyntheticFilter(), new SynchronizedFilter(),
- new TryWithResourcesJavacFilter(), new TryWithResourcesEcjFilter(),
- new PrivateEmptyNoArgConstructorFilter(),
- new StringSwitchJavacFilter(), new LombokGeneratedFilter() };
-
private final String className;
private final String superClassName;
private final boolean[] probes;
+ private final IFilter filter;
+
private final MethodCoverageImpl coverage;
private int currentLine = ISourceNode.UNKNOWN_LINE;
@@ -95,18 +85,20 @@ public class MethodAnalyzer extends MethodProbesVisitor
* method descriptor
* @param signature
* optional parameterized signature
- *
* @param probes
* recorded probe date of the containing class or
* <code>null</code> if the class is not executed at all
+ * @param filter
+ * filter
*/
- public MethodAnalyzer(final String className, final String superClassName,
+ MethodAnalyzer(final String className, final String superClassName,
final String name, final String desc, final String signature,
- final boolean[] probes) {
+ final boolean[] probes, final IFilter filter) {
super();
this.className = className;
this.superClassName = superClassName;
this.probes = probes;
+ this.filter = filter;
this.coverage = new MethodCoverageImpl(name, desc, signature);
}
@@ -126,11 +118,9 @@ public class MethodAnalyzer extends MethodProbesVisitor
@Override
public void accept(final MethodNode methodNode,
final MethodVisitor methodVisitor) {
- this.ignored.clear();
- for (final IFilter filter : FILTERS) {
- filter.filter(className, superClassName, methodNode, this);
- }
+ filter.filter(className, superClassName, methodNode, this);
+ methodVisitor.visitCode();
for (final TryCatchBlockNode n : methodNode.tryCatchBlocks) {
n.accept(methodVisitor);
}
@@ -143,6 +133,22 @@ public class MethodAnalyzer extends MethodProbesVisitor
}
private final Set<AbstractInsnNode> ignored = new HashSet<AbstractInsnNode>();
+
+ /**
+ * Instructions that should be merged form disjoint sets. Coverage
+ * information from instructions of one set will be merged into
+ * representative instruction of set.
+ *
+ * Each such set is represented as a singly linked list: each element except
+ * one references another element from the same set, element without
+ * reference - is a representative of this set.
+ *
+ * This map stores reference (value) for elements of sets (key).
+ */
+ private final Map<AbstractInsnNode, AbstractInsnNode> merged = new HashMap<AbstractInsnNode, AbstractInsnNode>();
+
+ private final Map<AbstractInsnNode, Instruction> nodeToInstruction = new HashMap<AbstractInsnNode, Instruction>();
+
private AbstractInsnNode currentNode;
public void ignore(final AbstractInsnNode fromInclusive,
@@ -154,6 +160,23 @@ public class MethodAnalyzer extends MethodProbesVisitor
ignored.add(toInclusive);
}
+ private AbstractInsnNode findRepresentative(AbstractInsnNode i) {
+ AbstractInsnNode r = merged.get(i);
+ while (r != null) {
+ i = r;
+ r = merged.get(i);
+ }
+ return i;
+ }
+
+ public void merge(AbstractInsnNode i1, AbstractInsnNode i2) {
+ i1 = findRepresentative(i1);
+ i2 = findRepresentative(i2);
+ if (i1 != i2) {
+ merged.put(i2, i1);
+ }
+ }
+
@Override
public void visitLabel(final Label label) {
currentLabel.add(label);
@@ -175,6 +198,7 @@ public class MethodAnalyzer extends MethodProbesVisitor
private void visitInsn() {
final Instruction insn = new Instruction(currentNode, currentLine);
+ nodeToInstruction.put(currentNode, insn);
instructions.add(insn);
if (lastInsn != null) {
insn.setPredecessor(lastInsn, 0);
@@ -342,6 +366,15 @@ public class MethodAnalyzer extends MethodProbesVisitor
for (final CoveredProbe p : coveredProbes) {
p.instruction.setCovered(p.branch);
}
+ // Merge:
+ for (final Instruction i : instructions) {
+ final AbstractInsnNode m = i.getNode();
+ final AbstractInsnNode r = findRepresentative(m);
+ if (r != m) {
+ ignored.add(m);
+ nodeToInstruction.get(r).merge(i);
+ }
+ }
// Report result:
coverage.ensureCapacity(firstLine, lastLine);
for (final Instruction i : instructions) {
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
new file mode 100644
index 00000000..e2c26d92
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.tree.MethodNode;
+
+/**
+ * Filter that combines other filters.
+ */
+public final class Filters implements IFilter {
+
+ /**
+ * Filter that does nothing.
+ */
+ public static final IFilter NONE = new Filters();
+
+ /**
+ * Filter that combines all other filters.
+ */
+ public static final IFilter ALL = new Filters(new EnumFilter(),
+ new SyntheticFilter(), new SynchronizedFilter(),
+ new TryWithResourcesJavacFilter(), new TryWithResourcesEcjFilter(),
+ new PrivateEmptyNoArgConstructorFilter(),
+ new StringSwitchJavacFilter(), new LombokGeneratedFilter());
+
+ private final IFilter[] filters;
+
+ private Filters(IFilter... filters) {
+ this.filters = filters;
+ }
+
+ public void filter(final String className, final String superClassName,
+ final MethodNode methodNode, final IFilterOutput output) {
+ for (final IFilter filter : filters) {
+ filter.filter(className, superClassName, methodNode, output);
+ }
+ }
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
index c24dc03d..cf25a0a2 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
@@ -30,4 +30,15 @@ public interface IFilterOutput {
*/
void ignore(AbstractInsnNode fromInclusive, AbstractInsnNode toInclusive);
+ /**
+ * Marks two instructions that should be merged during computation of
+ * coverage.
+ *
+ * @param i1
+ * first instruction
+ * @param i2
+ * second instruction
+ */
+ void merge(AbstractInsnNode i1, AbstractInsnNode i2);
+
}
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 571e4641..98575e80 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,7 +19,7 @@ import org.objectweb.asm.tree.MethodNode;
/**
* Filters methods annotated with <code>@lombok.Generated</code>.
*/
-public class LombokGeneratedFilter implements IFilter {
+public final class LombokGeneratedFilter implements IFilter {
public void filter(final String className, final String superClassName,
final MethodNode methodNode, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java
index 4f550407..bee274db 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java
@@ -130,6 +130,17 @@ public class Instruction {
return coveredBranches.cardinality();
}
+ /**
+ * Merges information about covered branches of given instruction into this
+ * instruction.
+ *
+ * @param instruction
+ * instruction from which to merge
+ */
+ public void merge(Instruction instruction) {
+ this.coveredBranches.or(instruction.coveredBranches);
+ }
+
@Override
public String toString() {
return coveredBranches.toString();