diff options
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(); |