From f24afa03aa5181db8cd7bf9961e147a16fcf382c Mon Sep 17 00:00:00 2001 From: ChristopherKoellner Date: Mon, 1 Nov 2021 23:42:37 +0100 Subject: [PATCH 1/5] Added filter to exclude branch that is most of the time not coverable --- .../targets/KotlinControlStructuresTarget.kt | 13 +++- .../internal/analysis/filter/Filters.java | 2 +- .../analysis/filter/KotlinForLoopFilter.java | 61 +++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt index cc8825df3c..f210587f8c 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt @@ -72,7 +72,7 @@ object KotlinControlStructuresTarget { private fun missedForBlock() { - for (j in i2()..i1()) { // assertPartlyCovered(3, 1) + for (j in i2()..i1()) { // assertPartlyCovered(2,0) nop() // assertNotCovered() } @@ -80,7 +80,16 @@ object KotlinControlStructuresTarget { private fun executedForBlock() { - for (j in i1()..i2()) { // assertFullyCovered(1, 3) + for (j in i1()..i2()) { // assertFullyCovered(0, 2) + nop() // assertFullyCovered() + } + + val limit = 10 // assertFullyCovered() + for (j in i1() until limit) { // assertFullyCovered(0,2) + nop() // assertFullyCovered() + } + + for (j in limit downTo i1()) { // assertFullyCovered(0,2) nop() // assertFullyCovered() } 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 fbfe522cfd..3fec553c26 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 @@ -42,7 +42,7 @@ public static IFilter all() { new EnumEmptyConstructorFilter(), new RecordsFilter(), new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(), new KotlinLateinitFilter(), new KotlinWhenFilter(), - new KotlinWhenStringFilter(), + new KotlinWhenStringFilter(), new KotlinForLoopFilter(), new KotlinUnsafeCastOperatorFilter(), new KotlinNotNullOperatorFilter(), new KotlinDefaultArgumentsFilter(), new KotlinInlineFilter(), diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java new file mode 100644 index 0000000000..6e314e33ed --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Fabian Mastenbroek - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.MethodNode; + +public class KotlinForLoopFilter implements IFilter { + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + final Matcher matcher = new Matcher(); + for (final AbstractInsnNode node : methodNode.instructions) { + matcher.match(node, output); + } + } + + private static class Matcher extends AbstractMatcher { + + public void match(final AbstractInsnNode start, IFilterOutput output) { + if (start.getOpcode() != Opcodes.IF_ICMPGE + && start.getOpcode() != Opcodes.IF_ICMPGT) { + return; + } + cursor = start; + LabelNode jumpTarget = ((JumpInsnNode) cursor).label; + if (isLoop(jumpTarget)) { + output.ignore(start, start); + } + } + + private boolean isLoop(LabelNode jumpTarget) { + nextIs(Opcodes.ILOAD); + nextIs(Opcodes.ISTORE); + nextIs(Opcodes.IINC); + // follow the jump node + for (AbstractInsnNode j = cursor; j != null; j = j.getNext()) { + if (j == jumpTarget) { + // if the node prior to the jump target matches + // we can be sure that this is the loop we are looking for + return j.getPrevious().getOpcode() == Opcodes.IF_ICMPLT + || j.getPrevious().getOpcode() == Opcodes.IF_ICMPNE; + } + } + return false; + } + } +} From 71479e58a149b2ad2913dc9ba35dabec85a91df6 Mon Sep 17 00:00:00 2001 From: ChristopherKoellner Date: Thu, 4 Nov 2021 08:25:44 +0100 Subject: [PATCH 2/5] Added test cases for KotlinForLoopFilter.java --- .../targets/KotlinControlStructuresTarget.kt | 19 ++- .../filter/KotlinForLoopFilterTest.java | 154 ++++++++++++++++++ .../analysis/filter/KotlinForLoopFilter.java | 12 +- 3 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt index f210587f8c..e56eb85682 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt @@ -72,7 +72,7 @@ object KotlinControlStructuresTarget { private fun missedForBlock() { - for (j in i2()..i1()) { // assertPartlyCovered(2,0) + for (j in i2()..i1()) { // assertPartlyCovered() nop() // assertNotCovered() } @@ -80,19 +80,30 @@ object KotlinControlStructuresTarget { private fun executedForBlock() { - for (j in i1()..i2()) { // assertFullyCovered(0, 2) + for (j in i1()..i2()) { // assertFullyCovered() nop() // assertFullyCovered() } val limit = 10 // assertFullyCovered() - for (j in i1() until limit) { // assertFullyCovered(0,2) + for (j in i1() until limit) { // assertFullyCovered() nop() // assertFullyCovered() } - for (j in limit downTo i1()) { // assertFullyCovered(0,2) + for (j in limit downTo i1()) { // assertFullyCovered() nop() // assertFullyCovered() } + for (i in 0 until i1()) { // assertFullyCovered() + nop() // assertFullyCovered() + } + + for (i in 0 until i2()) { // assertFullyCovered() + nop() // assertFullyCovered() + } + + for (i in i1() downTo 0) { // assertFullyCovered() + nop() // assertFullyCovered() + } } private fun missedForEachBlock() { diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java new file mode 100644 index 0000000000..24a90e92fc --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Fabian Mastenbroek - 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.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link KotlinForLoopFilter}. + */ +public class KotlinForLoopFilterTest extends FilterTestBase { + + private final KotlinForLoopFilter filter = new KotlinForLoopFilter(); + + /** + *
+	 * class Example {
+	 *   fun example() {
+	 *     for (j in 0 until i1()) {}
+	 *   }
+	 *   private fun i1() = 1
+	 * }
+	 * 
+ */ + @Test + public void should_filter_Kotlin_1_5_until() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "()V", null, null); + final Label label1 = new Label(); + final Label label2 = new Label(); + + m.visitInsn(Opcodes.ICONST_0); + m.visitVarInsn(Opcodes.ISTORE, 0); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "i1", "()I", + false); + m.visitVarInsn(Opcodes.ISTORE, 1); + m.visitVarInsn(Opcodes.ILOAD, 0); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitJumpInsn(Opcodes.IF_ICMPGE, label1); + final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ILOAD, 0); + m.visitVarInsn(Opcodes.ISTORE, 2); + m.visitInsn(Opcodes.IINC); + m.visitVarInsn(Opcodes.ILOAD, 0); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitJumpInsn(Opcodes.IF_ICMPLT, label2); + final AbstractInsnNode ignored2 = m.instructions.getLast(); + m.visitLabel(label1); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + assertIgnored(new Range(ignored1, ignored1), + new Range(ignored2, ignored2)); + } + + /** + *
+	 * class Example {
+	 *   fun example() {
+	 *     for (i in i1() downTo 0) {}
+	 *   }
+	 *   private fun i1() = 1
+	 * }
+	 * 
+ */ + @Test + public void should_filter_Kotlin_1_5_downTo() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "()V", null, null); + final Label label1 = new Label(); + final Label label2 = new Label(); + + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "i1", "()I", + false); + m.visitVarInsn(Opcodes.ISTORE, 0); + m.visitInsn(Opcodes.ICONST_0); + m.visitVarInsn(Opcodes.ISTORE, 1); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitJumpInsn(Opcodes.IF_ICMPGT, label1); + final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ILOAD, 0); + m.visitVarInsn(Opcodes.ISTORE, 2); + m.visitInsn(Opcodes.IINC); + m.visitInsn(Opcodes.ICONST_0); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitJumpInsn(Opcodes.IF_ICMPLE, label2); + final AbstractInsnNode ignored2 = m.instructions.getLast(); + m.visitLabel(label1); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + assertIgnored(new Range(ignored1, ignored1), + new Range(ignored2, ignored2)); + } + + /** + *
+	 * class Example {
+	 *   fun example() {
+	 *     val limit = 10
+	 *     for (j in limit downTo i1()) {}
+	 *   }
+	 *   private fun i1() = 1
+	 * }
+	 * 
+ */ + @Test + public void should_filter_Kotlin_1_5_downTo_val() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "()V", null, null); + final Label label1 = new Label(); + final Label label2 = new Label(); + + m.visitVarInsn(Opcodes.BIPUSH, 10); + m.visitVarInsn(Opcodes.ISTORE, 0); + m.visitVarInsn(Opcodes.ILOAD, 0); + m.visitVarInsn(Opcodes.ISTORE, 1); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "i1", "()I", + false); + m.visitVarInsn(Opcodes.ISTORE, 2); + m.visitVarInsn(Opcodes.ILOAD, 2); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitJumpInsn(Opcodes.IF_ICMPGT, label1); + final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ILOAD, 1); + m.visitVarInsn(Opcodes.ISTORE, 3); + m.visitInsn(Opcodes.IINC); + m.visitVarInsn(Opcodes.ILOAD, 3); + m.visitVarInsn(Opcodes.ILOAD, 2); + m.visitJumpInsn(Opcodes.IF_ICMPNE, label2); + final AbstractInsnNode ignored2 = m.instructions.getLast(); + m.visitLabel(label1); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + assertIgnored(new Range(ignored1, ignored1), + new Range(ignored2, ignored2)); + } + +} diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java index 6e314e33ed..f33f5ebbd5 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java @@ -18,6 +18,10 @@ import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; +/** + * Filters branches in bytecode that the Kotlin compiler generates for + * for loops as they are not coverable most of the time. + */ public class KotlinForLoopFilter implements IFilter { public void filter(final MethodNode methodNode, @@ -39,6 +43,8 @@ public void match(final AbstractInsnNode start, IFilterOutput output) { LabelNode jumpTarget = ((JumpInsnNode) cursor).label; if (isLoop(jumpTarget)) { output.ignore(start, start); + output.ignore(jumpTarget.getPrevious(), + jumpTarget.getPrevious()); } } @@ -51,8 +57,10 @@ private boolean isLoop(LabelNode jumpTarget) { if (j == jumpTarget) { // if the node prior to the jump target matches // we can be sure that this is the loop we are looking for - return j.getPrevious().getOpcode() == Opcodes.IF_ICMPLT - || j.getPrevious().getOpcode() == Opcodes.IF_ICMPNE; + int previousOpcode = j.getPrevious().getOpcode(); + return previousOpcode == Opcodes.IF_ICMPLT + || previousOpcode == Opcodes.IF_ICMPNE + || previousOpcode == Opcodes.IF_ICMPLE; } } return false; From 31d4861b51e1061ba49a22031df311ae38b99d71 Mon Sep 17 00:00:00 2001 From: ChristopherKoellner Date: Wed, 17 Nov 2021 14:31:06 +0100 Subject: [PATCH 3/5] Updated KotlinForLoopFilter.java and KotlinForLoopFilterTest --- .../filter/KotlinForLoopFilterTest.java | 5 +++- .../analysis/filter/KotlinForLoopFilter.java | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java index 24a90e92fc..9f2899380e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java @@ -52,6 +52,7 @@ public void should_filter_Kotlin_1_5_until() { m.visitVarInsn(Opcodes.ILOAD, 1); m.visitJumpInsn(Opcodes.IF_ICMPGE, label1); final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitLabel(label2); m.visitVarInsn(Opcodes.ILOAD, 0); m.visitVarInsn(Opcodes.ISTORE, 2); m.visitInsn(Opcodes.IINC); @@ -92,8 +93,9 @@ public void should_filter_Kotlin_1_5_downTo() { m.visitVarInsn(Opcodes.ILOAD, 1); m.visitJumpInsn(Opcodes.IF_ICMPGT, label1); final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitLabel(label2); m.visitVarInsn(Opcodes.ILOAD, 0); - m.visitVarInsn(Opcodes.ISTORE, 2); + m.visitVarInsn(Opcodes.ISTORE, 1); m.visitInsn(Opcodes.IINC); m.visitInsn(Opcodes.ICONST_0); m.visitVarInsn(Opcodes.ILOAD, 1); @@ -136,6 +138,7 @@ public void should_filter_Kotlin_1_5_downTo_val() { m.visitVarInsn(Opcodes.ILOAD, 1); m.visitJumpInsn(Opcodes.IF_ICMPGT, label1); final AbstractInsnNode ignored1 = m.instructions.getLast(); + m.visitLabel(label2); m.visitVarInsn(Opcodes.ILOAD, 1); m.visitVarInsn(Opcodes.ISTORE, 3); m.visitInsn(Opcodes.IINC); diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java index f33f5ebbd5..f4a1832b6d 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; +import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.JumpInsnNode; @@ -40,27 +41,29 @@ public void match(final AbstractInsnNode start, IFilterOutput output) { return; } cursor = start; - LabelNode jumpTarget = ((JumpInsnNode) cursor).label; - if (isLoop(jumpTarget)) { - output.ignore(start, start); - output.ignore(jumpTarget.getPrevious(), - jumpTarget.getPrevious()); + AbstractInsnNode loopLabel = start.getNext(); + if (loopLabel instanceof LabelNode) { + LabelNode jumpTarget = ((JumpInsnNode) cursor).label; + if (isLoop(jumpTarget, ((LabelNode) loopLabel).getLabel())) { + output.ignore(start, start); + output.ignore(jumpTarget.getPrevious(), + jumpTarget.getPrevious()); + } } } - private boolean isLoop(LabelNode jumpTarget) { + private boolean isLoop(LabelNode jumpTarget, Label label) { nextIs(Opcodes.ILOAD); nextIs(Opcodes.ISTORE); nextIs(Opcodes.IINC); // follow the jump node for (AbstractInsnNode j = cursor; j != null; j = j.getNext()) { if (j == jumpTarget) { - // if the node prior to the jump target matches + // if the label prior to the jump target matches // we can be sure that this is the loop we are looking for - int previousOpcode = j.getPrevious().getOpcode(); - return previousOpcode == Opcodes.IF_ICMPLT - || previousOpcode == Opcodes.IF_ICMPNE - || previousOpcode == Opcodes.IF_ICMPLE; + AbstractInsnNode previousOpcode = j.getPrevious(); + return ((JumpInsnNode) previousOpcode).label.getLabel() + .equals(label); } } return false; From a80722fda35d647af428acf8a67f5851172d8984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20R=C3=B6ssler?= Date: Wed, 17 Nov 2021 15:06:49 +0100 Subject: [PATCH 4/5] more precise variable naming --- .../internal/analysis/filter/KotlinForLoopFilter.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java index f4a1832b6d..da09bd2d86 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java @@ -41,10 +41,11 @@ public void match(final AbstractInsnNode start, IFilterOutput output) { return; } cursor = start; - AbstractInsnNode loopLabel = start.getNext(); - if (loopLabel instanceof LabelNode) { + AbstractInsnNode loopLabelNode = start.getNext(); + if (loopLabelNode instanceof LabelNode) { + Label loopLabel = ((LabelNode) loopLabelNode).getLabel(); LabelNode jumpTarget = ((JumpInsnNode) cursor).label; - if (isLoop(jumpTarget, ((LabelNode) loopLabel).getLabel())) { + if (isLoop(jumpTarget, loopLabel)) { output.ignore(start, start); output.ignore(jumpTarget.getPrevious(), jumpTarget.getPrevious()); @@ -52,7 +53,7 @@ public void match(final AbstractInsnNode start, IFilterOutput output) { } } - private boolean isLoop(LabelNode jumpTarget, Label label) { + private boolean isLoop(LabelNode jumpTarget, Label loopLabel) { nextIs(Opcodes.ILOAD); nextIs(Opcodes.ISTORE); nextIs(Opcodes.IINC); @@ -63,7 +64,7 @@ private boolean isLoop(LabelNode jumpTarget, Label label) { // we can be sure that this is the loop we are looking for AbstractInsnNode previousOpcode = j.getPrevious(); return ((JumpInsnNode) previousOpcode).label.getLabel() - .equals(label); + .equals(loopLabel); } } return false; From 066931b6f22e53f5e16d48db42a26f5768d8490d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20R=C3=B6ssler?= Date: Fri, 16 Dec 2022 19:25:03 +0100 Subject: [PATCH 5/5] update copyright --- .../core/internal/analysis/filter/KotlinForLoopFilterTest.java | 2 +- .../core/internal/analysis/filter/KotlinForLoopFilter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java index 9f2899380e..20f7607ea9 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilterTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors + * Copyright (c) 2009, 2022 Mountainminds GmbH & Co. KG and Contributors * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java index da09bd2d86..057e76b036 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinForLoopFilter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors + * Copyright (c) 2009, 2022 Mountainminds GmbH & Co. KG and Contributors * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0