+ * runBlocking {
+ * // suspending lambda without suspension points,
+ * // i.e. without invocations of suspending functions/lambdas
+ * }
+ *
+ *
+ * https://github.com/JetBrains/kotlin/commit/f4a1e27124f77b2ffca576f7393218373c6ae085
+ *
+ * @see #should_filter_suspending_lambdas()
+ */
+ @Test
+ public void should_filter_Kotlin_1_6_suspending_lambda_without_suspension_points() {
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "invokeSuspend",
+ "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
+ context.classAnnotations
+ .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+ m.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "kotlin/coroutines/intrinsics/IntrinsicsKt",
+ "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
+ final Range range1 = new Range();
+ range1.fromInclusive = m.instructions.getLast();
+ m.visitInsn(Opcodes.POP);
+
+ m.visitVarInsn(Opcodes.ALOAD, 0);
+ m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");
+
+ final Label dflt = new Label();
+ final Label state0 = new Label();
+ m.visitTableSwitchInsn(0, 0, dflt, state0);
+
+ m.visitLabel(state0);
+ {
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+ "throwOnFailure", "(Ljava/lang/Object;)V", false);
+ }
+ range1.toInclusive = m.instructions.getLast();
+
+ m.visitFieldInsn(Opcodes.GETSTATIC, "kotlin/Unit", "INSTANCE",
+ "Lkotlin/Unit;");
+ m.visitInsn(Opcodes.ARETURN);
+
+ m.visitLabel(dflt);
+ final Range range0 = new Range();
+ range0.fromInclusive = m.instructions.getLast();
+ m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
+ m.visitInsn(Opcodes.DUP);
+ m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
+ m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "java/lang/IllegalStateException", "",
+ "(Ljava/lang/String;)V", false);
+ m.visitInsn(Opcodes.ATHROW);
+ range0.toInclusive = m.instructions.getLast();
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range0, range1);
+ }
+
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
index 0fc360cb10..6dd47fd413 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
@@ -94,14 +94,23 @@ private void match(final MethodNode methodNode,
"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;");
}
- nextIsVar(Opcodes.ASTORE, "COROUTINE_SUSPENDED");
- nextIsVar(Opcodes.ALOAD, "this");
- nextIs(Opcodes.GETFIELD);
- nextIs(Opcodes.TABLESWITCH);
- if (cursor == null) {
- return;
+ final TableSwitchInsnNode s;
+ if (cursor != null
+ && Opcodes.POP == skipNonOpcodes(cursor.getNext())
+ .getOpcode()) {
+ // suspending lambda without suspension points
+ nextIs(Opcodes.POP);
+ s = nextIsStateSwitch();
+ if (s == null || s.labels.size() != 1) {
+ return;
+ }
+ } else {
+ nextIsVar(Opcodes.ASTORE, "COROUTINE_SUSPENDED");
+ s = nextIsStateSwitch();
+ if (s == null) {
+ return;
+ }
}
- final TableSwitchInsnNode s = (TableSwitchInsnNode) cursor;
final List ignore = new ArrayList(
s.labels.size() * 2);
@@ -174,6 +183,16 @@ private void match(final MethodNode methodNode,
}
}
+ private TableSwitchInsnNode nextIsStateSwitch() {
+ nextIsVar(Opcodes.ALOAD, "this");
+ nextIs(Opcodes.GETFIELD);
+ nextIs(Opcodes.TABLESWITCH);
+ if (cursor == null) {
+ return null;
+ }
+ return (TableSwitchInsnNode) cursor;
+ }
+
private void nextIsThrowOnFailure() {
final AbstractInsnNode c = cursor;
nextIsInvoke(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 7f8347b791..2dec020d62 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -30,6 +30,9 @@
New Features
Part of bytecode generated by the Kotlin compiler for inline value classes is
filtered out during generation of report
(GitHub #1475).
+
Part of bytecode generated by the Kotlin compiler for suspending lambdas
+ without suspension points is filtered out during generation of report
+ (GitHub #1283).
Method getEntries generated by the Kotlin compiler for enum
classes is filtered out during generation of report
(GitHub #1625).
From 5fdd9e6e4ac5db18b89433d13e7c34a144ef7a7c Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sun, 14 Jul 2024 18:52:04 +0200
Subject: [PATCH 024/163] Add builds with ECJ to GitHub Actions (#1649)
---
.github/workflows/ci.yml | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 60fddb7341..098418b581 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,10 +9,18 @@ jobs:
matrix:
include:
- jdk: 8
+ - jdk: 8
+ ecj: true
+ - jdk: 11
- jdk: 11
+ ecj: true
- jdk: 17
+ - jdk: 17
+ ecj: true
+ - jdk: 21
- jdk: 21
- name: JDK ${{ matrix.jdk }}
+ ecj: true
+ name: JDK ${{ matrix.jdk }}${{ matrix.ecj && ' with ECJ' || ''}}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
@@ -45,6 +53,7 @@ jobs:
run: |
mvn -V -B -e --no-transfer-progress \
verify -Djdk.version=${{ matrix.jdk }} -Dbytecode.version=${{ matrix.jdk }} \
+ ${{ matrix.ecj && '-Decj' || ''}} \
--toolchains=toolchains.xml
Windows:
runs-on: windows-2022
From 4f851cae6822289c55aff539786405d2bf473584 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sat, 20 Jul 2024 07:12:09 +0200
Subject: [PATCH 025/163] Reduce code duplication (#1652)
---
.../agent/rt/internal/ClassFileDumperTest.java | 10 +++-------
.../agent/rt/internal/CoverageTransformerTest.java | 11 +++--------
.../src/org/jacoco/core/test/TargetLoader.java | 12 ++++--------
3 files changed, 10 insertions(+), 23 deletions(-)
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
index c493d3416e..f8cae15ec2 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
@@ -14,12 +14,12 @@
import static org.junit.Assert.assertArrayEquals;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import org.jacoco.core.internal.InputStreams;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -66,13 +66,9 @@ public void testNoDumps() throws IOException {
private void assertContents(File location, String filename)
throws IOException {
InputStream in = new FileInputStream(new File(location, filename));
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- int b;
- while ((b = in.read()) != -1) {
- buffer.write(b);
- }
+ final byte[] bytes = InputStreams.readFully(in);
in.close();
- assertArrayEquals(contents, buffer.toByteArray());
+ assertArrayEquals(contents, bytes);
}
}
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
index d53e190570..63eba1a6f0 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
@@ -18,7 +18,6 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.IllegalClassFormatException;
@@ -27,6 +26,7 @@
import java.security.cert.Certificate;
import org.jacoco.core.JaCoCo;
+import org.jacoco.core.internal.InputStreams;
import org.jacoco.core.runtime.AbstractRuntime;
import org.jacoco.core.runtime.AgentOptions;
import org.junit.After;
@@ -245,14 +245,9 @@ private static byte[] getClassData(Class> clazz) throws IOException {
final String resource = "/" + clazz.getName().replace('.', '/')
+ ".class";
final InputStream in = clazz.getResourceAsStream(resource);
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[0x100];
- int len;
- while ((len = in.read(buffer)) != -1) {
- out.write(buffer, 0, len);
- }
+ final byte[] bytes = InputStreams.readFully(in);
in.close();
- return out.toByteArray();
+ return bytes;
}
private static class StubRuntime extends AbstractRuntime {
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java b/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
index 431516b5a9..84daacb3e8 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
@@ -12,12 +12,13 @@
*******************************************************************************/
package org.jacoco.core.test;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+import org.jacoco.core.internal.InputStreams;
+
/**
* Loads given classes from a byte arrays.
*/
@@ -68,14 +69,9 @@ public static byte[] getClassDataAsBytes(Class> clazz)
}
private static byte[] readBytes(InputStream in) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[0x100];
- int len;
- while ((len = in.read(buffer)) != -1) {
- out.write(buffer, 0, len);
- }
+ final byte[] bytes = InputStreams.readFully(in);
in.close();
- return out.toByteArray();
+ return bytes;
}
@Override
From eda47f1a223d387accedeaed7a3d4f9096fbe5ba Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 29 Jul 2024 22:13:36 +0300
Subject: [PATCH 026/163] Remove unused field (#1657)
---
.../internal/analysis/filter/KotlinLateinitFilterTest.java | 4 ----
1 file changed, 4 deletions(-)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
index c9b8dc87d7..5672d35260 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
@@ -12,7 +12,6 @@
*******************************************************************************/
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;
@@ -26,9 +25,6 @@ public class KotlinLateinitFilterTest extends FilterTestBase {
private final KotlinLateinitFilter filter = new KotlinLateinitFilter();
- private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
- "name", "()V", null, null);
-
@Test
public void should_filter_Kotlin_1_2() {
final MethodNode m = new MethodNode(0, "read", "()Ljava/lang/String;",
From 7222848bef6a43a15a0809596f024544ecf38397 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 29 Jul 2024 22:40:56 +0300
Subject: [PATCH 027/163] Add missing `Test` annotation to method in
`FileOutputTest` (#1658)
This was overlooked in aa16a7c25cfc119ba3486bb114d3d54dc1bcca6c
---
.../src/org/jacoco/agent/rt/internal/output/FileOutputTest.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
index ccfc2b2375..9422020e42 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
@@ -108,6 +108,7 @@ public void startup_should_throw_OverlappingFileLockException_when_execfile_is_p
}
}
+ @Test
public void startup_should_throw_InterruptedIOException_when_execfile_is_locked_and_thread_is_interrupted()
throws Exception {
if (JavaVersion.current().isBefore("1.6")) {
From ad12d46652db64975a2fb6718a941c3ada2ea6be Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Tue, 30 Jul 2024 15:55:32 +0200
Subject: [PATCH 028/163] Fix typo: replace two consecutive dots in javadoc by
one (#1659)
---
.../jacoco/report/internal/html/page/PackageSourcePage.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
index fc1f24b4f0..7e4b0cc48d 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
@@ -70,8 +70,7 @@ public void render() throws IOException {
/**
* Returns the link to the source file page of the source file with the
- * given name. If no source file was located, null is
- * returned..
+ * given name. If no source file was located, null is returned.
*/
ILinkable getSourceFilePage(final String name) {
return sourceFilePages.get(name);
From 1ba265ee1cd5bc354ee11ac1ca7a2ce8e71d3a98 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Wed, 31 Jul 2024 00:11:48 +0200
Subject: [PATCH 029/163] Fix interpretation of Kotlin SMAP (#1525)
---
.../kotlin/KotlinCrossinlineTest.java | 32 ++++
.../kotlin/targets/KotlinCrossinlineTarget.kt | 37 +++++
.../filter/KotlinInlineFilterTest.java | 150 +++++++++++++++---
.../analysis/filter/KotlinInlineFilter.java | 18 +--
org.jacoco.doc/docroot/doc/changes.html | 6 +
5 files changed, 209 insertions(+), 34 deletions(-)
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCrossinlineTest.java
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCrossinlineTarget.kt
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCrossinlineTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCrossinlineTest.java
new file mode 100644
index 0000000000..ce1f317372
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCrossinlineTest.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinCrossinlineTarget;
+
+/**
+ * Test of code coverage in {@link KotlinCrossinlineTarget}.
+ */
+public class KotlinCrossinlineTest extends ValidationTestBase {
+
+ public KotlinCrossinlineTest() {
+ super(KotlinCrossinlineTarget.class);
+ }
+
+ @Override
+ public void all_missed_instructions_should_have_line_number() {
+ // missed instructions without line number in inline function
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCrossinlineTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCrossinlineTarget.kt
new file mode 100644
index 0000000000..f0a58015de
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCrossinlineTarget.kt
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
+/**
+ * Test target for `crossinline`.
+ */
+object KotlinCrossinlineTarget {
+
+ inline fun example(crossinline lambda: () -> Unit): () -> Unit { // assertEmpty()
+ return { // assertNotCovered()
+ lambda() // assertEmpty()
+ } // assertEmpty()
+ } // assertEmpty()
+
+ @JvmStatic
+ fun main(args: Array) {
+
+ example { // assertFullyCovered()
+ nop() // assertEmpty()
+ }() // assertEmpty()
+
+ }
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java
index 2e7d1622c8..73b77a097e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java
@@ -22,6 +22,7 @@
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;
/**
@@ -36,6 +37,7 @@ public class KotlinInlineFilterTest extends FilterTestBase {
@Test
public void should_filter() {
+ context.className = "CallsiteKt";
context.sourceFileName = "callsite.kt";
context.sourceDebugExtension = "" //
+ "SMAP\n" //
@@ -113,6 +115,7 @@ public void should_filter() {
*/
@Test
public void should_filter_when_in_same_file() {
+ context.className = "Callsite";
context.sourceFileName = "example.kt";
context.sourceDebugExtension = "" //
+ "SMAP\n" //
@@ -173,6 +176,7 @@ public void should_filter_when_in_same_file() {
*/
@Test
public void should_filter_without_parsing_KotlinDebug_stratum() {
+ context.className = "ExampleKt";
context.sourceFileName = "Example.kt";
context.sourceDebugExtension = "" //
+ "SMAP\n" //
@@ -204,6 +208,127 @@ public void should_filter_without_parsing_KotlinDebug_stratum() {
assertIgnored(expectedRanges.toArray(new Range[0]));
}
+ /**
+ *
+ * package a;
+ *
+ * inline fun testInline() {} // line 7
+ *
+ */
+ @Test
+ public void should_stop_parsing_at_KotlinDebug_stratum() {
+ final KotlinSMAP smap = new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" // OutputFileName=Example.kt
+ + "Kotlin\n" // DefaultStratumId=Kotlin
+ + "*S Kotlin\n" // StratumID=Kotlin
+ + "*F\n" // FileSection
+ + "+ 1 Example.kt\n" // FileID=1,FileName=Example.kt
+ + "ExampleKt\n" //
+ + "*L\n" // LineSection
+ + "1#1,3:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=3,OutputStartLine=1
+ + "1#1:4\n" // InputStartLine=1,LineFileID=1,OutputStartLine=4
+ + "*S KotlinDebug\n" // StratumID=KotlinDebug
+ + "xxx");
+ assertEquals(2, smap.mappings().size());
+ KotlinSMAP.Mapping mapping = smap.mappings().get(0);
+ assertEquals("ExampleKt", mapping.inputClassName());
+ assertEquals(1, mapping.inputStartLine());
+ assertEquals(3, mapping.repeatCount());
+ assertEquals(1, mapping.outputStartLine());
+ mapping = smap.mappings().get(1);
+ assertEquals("ExampleKt", mapping.inputClassName());
+ assertEquals(1, mapping.inputStartLine());
+ assertEquals(1, mapping.repeatCount());
+ assertEquals(4, mapping.outputStartLine());
+ }
+
+ @Test
+ public void should_throw_exception_when_not_an_SMAP_Header() {
+ try {
+ new KotlinSMAP("", "xxx");
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_OutputFileName_does_not_match_SourceFileName() {
+ try {
+ new KotlinSMAP("", "SMAP\n" //
+ + "Example.kt\n");
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: Example.kt", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_DefaultStratumId_is_not_Kotlin() {
+ try {
+ new KotlinSMAP("Servlet.java", "SMAP\n" //
+ + "Servlet.java\n" // OutputFileName=Servlet.java
+ + "JSP\n"); // DefaultStratumId=JSP
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: JSP", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_first_StratumId_is_not_Kotlin() {
+ try {
+ new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" // OutputFileName=Example.kt
+ + "Kotlin\n" // DefaultStratumId=Kotlin
+ + "*S KotlinDebug\n"); // StratumID=KotlinDebug
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: *S KotlinDebug",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_StratumSection_does_not_start_with_FileSection() {
+ try {
+ new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" //
+ + "Kotlin\n" //
+ + "*S Kotlin\n" //
+ + "xxx"); //
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_FileSection_contains_unexpected_FileInfo() {
+ try {
+ new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" //
+ + "Kotlin\n" //
+ + "*S Kotlin\n" //
+ + "*F\n" //
+ + "xxx"); //
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_LineSection_contains_unexpected_LineInfo() {
+ try {
+ new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" //
+ + "Kotlin\n" //
+ + "*S Kotlin\n" //
+ + "*F\n" //
+ + "*L\n" //
+ + "xxx"); //
+ fail("exception expected");
+ } catch (final IllegalStateException e) {
+ assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_throw_exception_when_LineInfo_does_not_have_FileID() {
+ try {
+ new KotlinSMAP("Example.kt", "SMAP\n" //
+ + "Example.kt\n" //
+ + "Kotlin\n" //
+ + "*S Kotlin\n" //
+ + "*F\n" //
+ + "*L\n" //
+ + "1:1\n"); // InputStartLine=1,OutputStartLine=1
+ fail("exception expected");
+ } catch (final NullPointerException e) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
index 43e328e977..55c2d77fbf 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
@@ -12,13 +12,6 @@
*******************************************************************************/
package org.jacoco.core.internal.analysis.filter;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.BitSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.MethodNode;
@@ -57,85 +50,18 @@ public void filter(final MethodNode methodNode,
}
}
- private static int getFirstGeneratedLineNumber(
- final String currentClassName, final String sourceFileName,
- final String smap) {
- try {
- final BufferedReader br = new BufferedReader(
- new StringReader(smap));
- expectLine(br, "SMAP");
- // OutputFileName
- expectLine(br, sourceFileName);
- // DefaultStratumId
- expectLine(br, "Kotlin");
- // StratumSection
- expectLine(br, "*S Kotlin");
- // FileSection
- expectLine(br, "*F");
- final BitSet sourceFileIds = new BitSet();
- String line;
- while (!"*L".equals(line = br.readLine())) {
- final Matcher m = FILE_INFO_PATTERN.matcher(line);
- if (!m.matches()) {
- throw new IllegalStateException(
- "Unexpected SMAP line: " + line);
- }
- // See
- // https://github.com/JetBrains/kotlin/blob/2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt#L120-L121
- // https://github.com/JetBrains/kotlin/blob/2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/SourceInfo.kt#L38-L41
- final String className = br.readLine();
- if (currentClassName.equals(className)) {
- sourceFileIds.set(Integer.parseInt(m.group(1)));
- }
- }
- // LineSection
- int min = Integer.MAX_VALUE;
- while (true) {
- line = br.readLine();
- if (line.equals("*E") || line.equals("*S KotlinDebug")) {
- break;
- }
- final Matcher m = LINE_INFO_PATTERN.matcher(line);
- if (!m.matches()) {
- throw new IllegalStateException(
- "Unexpected SMAP line: " + line);
- }
- final int inputStartLine = Integer.parseInt(m.group(1));
- final int lineFileID = Integer
- .parseInt(m.group(2).substring(1));
- final int outputStartLine = Integer.parseInt(m.group(4));
- if (sourceFileIds.get(lineFileID)
- && inputStartLine == outputStartLine) {
- continue;
- }
- min = Math.min(outputStartLine, min);
+ private static int getFirstGeneratedLineNumber(final String className,
+ final String sourceFileName, final String smap) {
+ int min = Integer.MAX_VALUE;
+ for (KotlinSMAP.Mapping mapping : new KotlinSMAP(sourceFileName, smap)
+ .mappings()) {
+ if (className.equals(mapping.inputClassName())
+ && mapping.inputStartLine() == mapping.outputStartLine()) {
+ continue;
}
- return min;
- } catch (final IOException e) {
- // Must not happen with StringReader
- throw new AssertionError(e);
+ min = Math.min(mapping.outputStartLine(), min);
}
+ return min;
}
- private static void expectLine(final BufferedReader br,
- final String expected) throws IOException {
- final String line = br.readLine();
- if (!expected.equals(line)) {
- throw new IllegalStateException("Unexpected SMAP line: " + line);
- }
- }
-
- private static final Pattern LINE_INFO_PATTERN = Pattern.compile("" //
- + "([0-9]++)" // InputStartLine
- + "(#[0-9]++)?+" // LineFileID
- + "(,[0-9]++)?+" // RepeatCount
- + ":([0-9]++)" // OutputStartLine
- + "(,[0-9]++)?+" // OutputLineIncrement
- );
-
- private static final Pattern FILE_INFO_PATTERN = Pattern.compile("" //
- + "\\+ ([0-9]++)" // FileID
- + " (.++)" // FileName
- );
-
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java
new file mode 100644
index 0000000000..8062199ae4
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Parsed representation of SourceDebugExtension attribute.
+ */
+final class KotlinSMAP {
+
+ public static final class Mapping {
+ private final String inputClassName;
+ private final int inputStartLine;
+ private final int repeatCount;
+ private final int outputStartLine;
+
+ /**
+ * Creates a new mapping.
+ *
+ * @param inputClassName
+ * name of input class
+ * @param inputStartLine
+ * starting line in input
+ * @param repeatCount
+ * number of mapped lines
+ * @param outputStartLine
+ * starting line in output
+ */
+ Mapping(final String inputClassName, final int inputStartLine,
+ final int repeatCount, final int outputStartLine) {
+ this.inputClassName = inputClassName;
+ this.inputStartLine = inputStartLine;
+ this.repeatCount = repeatCount;
+ this.outputStartLine = outputStartLine;
+ }
+
+ /**
+ * @return name of input class
+ */
+ public String inputClassName() {
+ return inputClassName;
+ }
+
+ /**
+ * @return starting line in input
+ */
+ public int inputStartLine() {
+ return inputStartLine;
+ }
+
+ /**
+ * @return number of mapped lines
+ */
+ public int repeatCount() {
+ return repeatCount;
+ }
+
+ /**
+ * @return starting line in output
+ */
+ public int outputStartLine() {
+ return outputStartLine;
+ }
+ }
+
+ private final ArrayList mappings = new ArrayList();
+
+ /**
+ * Returns list of mappings.
+ *
+ * @return list of mappings
+ */
+ public List mappings() {
+ return mappings;
+ }
+
+ /**
+ * Creates parsed representation of provided SourceDebugExtension attribute.
+ *
+ * @param sourceFileName
+ * the name of the source file from which the class with SMAP was
+ * compiled
+ * @param smap
+ * value of SourceDebugExtension attribute to parse
+ */
+ public KotlinSMAP(final String sourceFileName, final String smap) {
+ try {
+ final BufferedReader br = new BufferedReader(
+ new StringReader(smap));
+ // Header
+ expectLine(br, "SMAP");
+ // OutputFileName
+ expectLine(br, sourceFileName);
+ // DefaultStratumId
+ expectLine(br, "Kotlin");
+ // StratumSection
+ expectLine(br, "*S Kotlin");
+ // FileSection
+ expectLine(br, "*F");
+ final HashMap inputClassNames = new HashMap();
+ String line;
+ while (!"*L".equals(line = br.readLine())) {
+ final Matcher m = FILE_INFO_PATTERN.matcher(line);
+ if (!m.matches()) {
+ throw new IllegalStateException(
+ "Unexpected SMAP line: " + line);
+ }
+ final int id = Integer.parseInt(m.group(1));
+ // See
+ // https://github.com/JetBrains/kotlin/blob/2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt#L120-L121
+ // https://github.com/JetBrains/kotlin/blob/2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/SourceInfo.kt#L38-L41
+ final String className = br.readLine();
+ inputClassNames.put(id, className);
+ }
+ // LineSection
+ while (true) {
+ line = br.readLine();
+ if (line.equals("*E") || line.equals("*S KotlinDebug")) {
+ break;
+ }
+ final Matcher m = LINE_INFO_PATTERN.matcher(line);
+ if (!m.matches()) {
+ throw new IllegalStateException(
+ "Unexpected SMAP line: " + line);
+ }
+ final int inputStartLine = Integer.parseInt(m.group(1));
+ final int lineFileID = Integer
+ .parseInt(m.group(2).substring(1));
+ final String repeatCountOptional = m.group(3);
+ final int repeatCount = repeatCountOptional != null
+ ? Integer.parseInt(repeatCountOptional.substring(1))
+ : 1;
+ final int outputStartLine = Integer.parseInt(m.group(4));
+ mappings.add(new Mapping(inputClassNames.get(lineFileID),
+ inputStartLine, repeatCount, outputStartLine));
+ }
+ } catch (final IOException e) {
+ // Must not happen with StringReader
+ throw new AssertionError(e);
+ }
+ }
+
+ private static void expectLine(final BufferedReader br,
+ final String expected) throws IOException {
+ final String line = br.readLine();
+ if (!expected.equals(line)) {
+ throw new IllegalStateException("Unexpected SMAP line: " + line);
+ }
+ }
+
+ private static final Pattern LINE_INFO_PATTERN = Pattern.compile("" //
+ + "([0-9]++)" // InputStartLine
+ + "(#[0-9]++)?+" // LineFileID
+ + "(,[0-9]++)?+" // RepeatCount
+ + ":([0-9]++)" // OutputStartLine
+ + "(,[0-9]++)?+" // OutputLineIncrement
+ );
+
+ private static final Pattern FILE_INFO_PATTERN = Pattern.compile("" //
+ + "\\+ ([0-9]++)" // FileID
+ + " (.++)" // FileName
+ );
+
+}
From 3935957ba891cca5e0a88d8639becad05689154c Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sun, 4 Aug 2024 22:05:04 +0200
Subject: [PATCH 032/163] Remove unused import (#1666)
---
.../jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java
index 6eb1d5760d..95745918a5 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java
@@ -13,7 +13,6 @@
package org.jacoco.core.test.validation.kotlin;
import org.jacoco.core.test.validation.ValidationTestBase;
-import org.jacoco.core.test.validation.kotlin.targets.KotlinElvisOperatorTarget;
import org.jacoco.core.test.validation.kotlin.targets.KotlinSafeCastTarget;
/**
From c2d805a8c73615c35d0eea5a7887f7eff412fef4 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sun, 4 Aug 2024 22:50:25 +0200
Subject: [PATCH 033/163] Add missing test (#1667)
It was forgotten in commit 281538bc74d9f09f5b0d83250a4435b5c2732e21
---
.../jacoco/core/internal/analysis/ClassAnalyzerTest.java | 7 +++++++
1 file changed, 7 insertions(+)
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 84bb3ba21a..ee01b9ac04 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,6 +60,13 @@ public void testMethodFilter_Empty() {
assertEquals(0, coverage.getMethods().size());
}
+ @Test
+ public void should_collect_annotations() {
+ assertTrue(analyzer.getClassAnnotations().isEmpty());
+ analyzer.visitAnnotation("Lpkg/Annotation;", true);
+ assertTrue(analyzer.getClassAnnotations().contains("Lpkg/Annotation;"));
+ }
+
@Test
public void should_collect_attributes() {
assertTrue(analyzer.getClassAttributes().isEmpty());
From 6492b4035fcd44c9fd4553d30b8576c2cb42c278 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 6 Aug 2024 09:59:30 +0200
Subject: [PATCH 034/163] Bump actions/upload-artifact from 4.3.4 to 4.3.5
(#1673)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/0b2256b8c012f0828dc542b3febcab082c67f72b...89ef406dd8d7e03cfd12d9e0a4a378f454709029)
---
updated-dependencies:
- dependency-name: actions/upload-artifact
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 098418b581..7f8a681f15 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -91,7 +91,7 @@ jobs:
mvn -V -B -e --no-transfer-progress \
verify -Djdk.version=6 -Dbytecode.version=5 \
--toolchains=toolchains.xml
- - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
+ - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
id: artifact-upload-step
with:
name: jacoco
From 2940177428cdad9d669cec32dc3459fd857438a6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 6 Aug 2024 11:46:54 +0200
Subject: [PATCH 035/163] Bump actions/setup-java from 4.2.1 to 4.2.2 (#1672)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/99b8673ff64fbf99d8d325f52d9a5bdedb8483e9...6a0805fcefea3d4657a47ac4c165951e33482018)
---
updated-dependencies:
- dependency-name: actions/setup-java
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7f8a681f15..67b3a08b9b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
+ - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2
with:
distribution: 'zulu'
java-version: |
@@ -59,7 +59,7 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
+ - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2
with:
distribution: 'zulu'
java-version: |
From e4ab395b8c37e19dc73b4396a259281384122297 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 8 Aug 2024 13:44:54 +0200
Subject: [PATCH 036/163] Upgrade Kotlin to 2.0.10 (#1674)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evgeny Mandrikov
---
org.jacoco.core.test.validation.kotlin/pom.xml | 2 +-
org.jacoco.core.test.validation/pom.xml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml
index b3984fc546..a420a3e6fb 100644
--- a/org.jacoco.core.test.validation.kotlin/pom.xml
+++ b/org.jacoco.core.test.validation.kotlin/pom.xml
@@ -25,7 +25,7 @@
JaCoCo :: Test :: Core :: Validation Kotlin
- 2.0.0
+ 2.0.10
diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml
index 0dae8d4d8c..6060229c79 100644
--- a/org.jacoco.core.test.validation/pom.xml
+++ b/org.jacoco.core.test.validation/pom.xml
@@ -504,7 +504,7 @@
-
+
2216
@@ -535,7 +535,7 @@
-
+
2216
From a4f2b16c23b1bfba0419edc1697cb13775c043a9 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 12 Aug 2024 08:08:18 +0200
Subject: [PATCH 037/163] Add missing javadoc (#1677)
It was forgotten in commit 36b4e9c7103441d556a1667b4485960f5bdfeff8
---
.../core/internal/instr/CondyProbeArrayStrategyTest.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java
index 13bca2efc6..e618e245bd 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java
@@ -27,6 +27,9 @@
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
+/**
+ * Unit test for {@link CondyProbeArrayStrategy}.
+ */
public class CondyProbeArrayStrategyTest {
private CondyProbeArrayStrategy strategy;
From a06b277e824d2b1667fab85e03cb58153c474741 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 12 Aug 2024 08:44:37 +0200
Subject: [PATCH 038/163] Upgrade Groovy to 3.0.22 (#1678)
---
org.jacoco.core.test.validation.groovy/pom.xml | 2 +-
org.jacoco.core.test.validation/pom.xml | 18 ++++++++----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml
index a06c0d3518..0db9822cae 100644
--- a/org.jacoco.core.test.validation.groovy/pom.xml
+++ b/org.jacoco.core.test.validation.groovy/pom.xml
@@ -27,7 +27,7 @@
3.0.0
- 3.0.21
+ 3.0.22
diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml
index 6060229c79..c9b4001d9a 100644
--- a/org.jacoco.core.test.validation/pom.xml
+++ b/org.jacoco.core.test.validation/pom.xml
@@ -368,7 +368,7 @@
18
-
+
1618
@@ -395,7 +395,7 @@
19
-
+
1619
@@ -422,7 +422,7 @@
20
-
+
1620
@@ -449,7 +449,7 @@
21
-
+
1621
@@ -477,7 +477,7 @@
22
-
+
1622
@@ -506,7 +506,7 @@
22
-
+
1623
@@ -519,9 +519,7 @@
../org.jacoco.core.test.validation.java14../org.jacoco.core.test.validation.java16../org.jacoco.core.test.validation.java21
-
../org.jacoco.core.test.validation.scala
@@ -537,7 +535,7 @@
22
-
+
1624
@@ -550,7 +548,7 @@
../org.jacoco.core.test.validation.java14../org.jacoco.core.test.validation.java16../org.jacoco.core.test.validation.java21
-
../org.jacoco.core.test.validation.scala
From 52e6e50d8490fca597092127d519947f48dca733 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 12 Aug 2024 09:10:15 +0200
Subject: [PATCH 039/163] Require at least Maven 3.6.3 for build (#1681)
---
org.jacoco.build/pom.xml | 2 +-
org.jacoco.doc/docroot/doc/build.html | 2 +-
org.jacoco.doc/docroot/doc/changes.html | 6 ++++++
org.jacoco.doc/docroot/doc/environment.html | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index 8476939e33..3e07eeb632 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -520,7 +520,7 @@
- [3.5.4,3.8.2),(3.8.2,)
+ [3.6.3,3.8.2),(3.8.2,)The rules for repo1.maven.org are that pom.xml files should not include repository definitions.
diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html
index 89ed086914..efab7c1556 100644
--- a/org.jacoco.doc/docroot/doc/build.html
+++ b/org.jacoco.doc/docroot/doc/build.html
@@ -24,7 +24,7 @@
Build
The JaCoCo build is based on Maven and
can be locally executed on every machine with a proper
environment setup. In particular you need at
- least Maven 3.5.4 and JDK 17
+ least Maven 3.6.3 and JDK 17
installations. Developers are encouraged to run the build before every commit
to ensure consistency of the source tree.
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 2dd5dcb1b5..4bddc1488a 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -44,6 +44,12 @@
The JaCoCo build is based on Maven
- and requires at least Maven 3.5.4 and JDK 17.
+ and requires at least Maven 3.6.3 and JDK 17.
See the build description for details.
From 137173919422f5e7fe81ace22bc9f0ae47e8cd54 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 12 Aug 2024 11:53:49 +0200
Subject: [PATCH 040/163] Fix ClassAnalyzerTest (#1668)
This was overlooked in commit 4d4d02e6dbfb17f454bf4579ee13209e9f035154
---
.../internal/analysis/ClassAnalyzerTest.java | 34 +++++++++++++++----
1 file changed, 28 insertions(+), 6 deletions(-)
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 ee01b9ac04..44186568a6 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
@@ -21,6 +21,7 @@
import org.junit.Test;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
/**
* Unit tests for {@link ClassAnalyzer}.
@@ -39,27 +40,48 @@ public void setup() {
}
@Test(expected = IllegalStateException.class)
- public void testAnalyzeInstrumentedClass1() {
+ public void should_throw_IllegalStateException_when_class_is_instrumented_with_data_field() {
analyzer.visitField(InstrSupport.DATAFIELD_ACC,
InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC, null,
null);
}
@Test(expected = IllegalStateException.class)
- public void testAnalyzeInstrumentedClass2() {
+ public void should_throw_IllegalStateException_when_class_is_instrumented_with_init_method() {
analyzer.visitMethod(InstrSupport.INITMETHOD_ACC,
InstrSupport.INITMETHOD_NAME, InstrSupport.INITMETHOD_DESC,
null, null);
}
+ /**
+ * @see #should_add_non_empty_methods()
+ */
@Test
- public void testMethodFilter_Empty() {
- final MethodProbesVisitor mv = analyzer.visitMethod(0, "foo", "()V",
- null, null);
- mv.visitEnd();
+ public void should_not_add_empty_methods() {
+ final MethodNode m = new MethodNode(0, "foo", "()V", null, null);
+
+ final MethodProbesVisitor mv = analyzer.visitMethod(m.access, m.name,
+ m.desc, m.signature, m.exceptions.toArray(new String[0]));
+ mv.accept(m, mv);
+
assertEquals(0, coverage.getMethods().size());
}
+ /**
+ * @see #should_not_add_empty_methods()
+ */
+ @Test
+ public void should_add_non_empty_methods() {
+ final MethodNode m = new MethodNode(0, "foo", "()V", null, null);
+ m.visitInsn(Opcodes.RETURN);
+
+ final MethodProbesVisitor mv = analyzer.visitMethod(m.access, m.name,
+ m.desc, m.signature, m.exceptions.toArray(new String[0]));
+ mv.accept(m, mv);
+
+ assertEquals(1, coverage.getMethods().size());
+ }
+
@Test
public void should_collect_annotations() {
assertTrue(analyzer.getClassAnnotations().isEmpty());
From d867bbcfab8edaba0b41b2ca233f52e4dffaee82 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 12 Aug 2024 12:41:10 +0200
Subject: [PATCH 041/163] NormalizedFileNames should add prefix instead of
suffix (#1660)
Otherwise it changes file extensions.
---
org.jacoco.doc/docroot/doc/changes.html | 3 +++
.../internal/NormalizedFileNamesTest.java | 24 +++++++++----------
.../report/internal/NormalizedFileNames.java | 4 ++--
3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 4bddc1488a..27af4034e4 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -42,6 +42,9 @@
Fixed bugs
Fixed interpretation of Kotlin SMAP
(GitHub #1525).
+
File extensions are preserved in HTML report in case of clashes of normalized
+ file names
+ (GitHub #1660).
Calculation of line coverage for Kotlin inline functions
+
Calculation of line coverage for Kotlin inline functions
(GitHub #1670).
+
Calculation of line coverage for Kotlin inline functions
+ with reified type parameter
+ (GitHub #1670,
+ #1700).
+
Calculation of coverage for Kotlin JvmSynthetic functions
+ (GitHub #1700).
Experimental support for Java 24 class files
(GitHub #1631).
Part of bytecode generated by the Kotlin Compose compiler plugin is
From 357a11dfce01095c8369bcdafec7d9a1251cf9fb Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 13 Sep 2024 09:07:52 +0000
Subject: [PATCH 052/163] Bump actions/setup-java from 4.2.2 to 4.3.0 (#1702)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/6a0805fcefea3d4657a47ac4c165951e33482018...2dfa2011c5b2a0f1489bf9e433881c92c1631f88)
---
updated-dependencies:
- dependency-name: actions/setup-java
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2f388c40cf..85d617e54e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2
+ - uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
with:
distribution: 'zulu'
java-version: |
@@ -59,7 +59,7 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2
+ - uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
with:
distribution: 'zulu'
java-version: |
From 517d8e5dd523a43c73e42bc06b99de76290056c5 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 16 Sep 2024 10:21:26 +0200
Subject: [PATCH 053/163] Use Maven Wrapper (#1707)
---
.azure-pipelines/azure-pipelines.yml | 12 +-
.github/workflows/ci.yml | 4 +-
.mvn/wrapper/maven-wrapper.properties | 19 ++
mvnw | 259 ++++++++++++++++++++++++++
mvnw.cmd | 149 +++++++++++++++
5 files changed, 432 insertions(+), 11 deletions(-)
create mode 100644 .mvn/wrapper/maven-wrapper.properties
create mode 100755 mvnw
create mode 100644 mvnw.cmd
diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml
index 2726d645ce..485fbb31e9 100644
--- a/.azure-pipelines/azure-pipelines.yml
+++ b/.azure-pipelines/azure-pipelines.yml
@@ -77,12 +77,6 @@ jobs:
" > toolchains.xml
displayName: Setup JDK
- - bash: |
- set -e
- mkdir .maven
- curl -L "https://archive.apache.org/dist/maven/maven-3/3.8.3/binaries/apache-maven-3.8.3-bin.tar.gz" -o .maven/maven.tar.gz
- tar -xzf .maven/maven.tar.gz -C .maven --strip-components 1
- displayName: Setup Maven
- bash: |
if [[ "$JDK_VERSION" -ge "17" ]]; then
export JAVA_HOME=$PWD/.jdk
@@ -90,17 +84,17 @@ jobs:
export JAVA_HOME=$JAVA_HOME_17_X64
fi
if [[ "$BUILD_SOURCEBRANCH" == "refs/heads/master" && "$JDK_VERSION" == "5" ]]; then
- .maven/bin/mvn -V -B -e --no-transfer-progress -f org.jacoco.build \
+ ./mvnw -V -B -e --no-transfer-progress -f org.jacoco.build \
verify -Djdk.version=$JDK_VERSION -Dbytecode.version=$JDK_VERSION \
deploy:deploy -DdeployAtEnd \
--toolchains=toolchains.xml --settings=.azure-pipelines/maven-settings.xml
elif [[ "$BUILD_SOURCEBRANCH" == "refs/heads/master" && "$JDK_VERSION" == "11" ]]; then
- .maven/bin/mvn -V -B -e --no-transfer-progress -f org.jacoco.build \
+ ./mvnw -V -B -e --no-transfer-progress -f org.jacoco.build \
verify -Djdk.version=$JDK_VERSION -Dbytecode.version=$JDK_VERSION \
sonar:sonar \
--toolchains=toolchains.xml --settings=.azure-pipelines/maven-settings.xml
else
- .maven/bin/mvn -V -B -e --no-transfer-progress \
+ ./mvnw -V -B -e --no-transfer-progress \
verify -Djdk.version=$JDK_VERSION -Dbytecode.version=$JDK_VERSION -Decj=${ECJ:-} \
--toolchains=toolchains.xml
fi
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 85d617e54e..f08ad9abec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -51,7 +51,7 @@ jobs:
" > toolchains.xml
- name: 'Build'
run: |
- mvn -V -B -e --no-transfer-progress \
+ ./mvnw -V -B -e --no-transfer-progress \
verify -Djdk.version=${{ matrix.jdk }} -Dbytecode.version=${{ matrix.jdk }} \
${{ matrix.ecj && '-Decj' || ''}} \
--toolchains=toolchains.xml
@@ -88,7 +88,7 @@ jobs:
- name: 'Build'
shell: bash
run: |
- mvn -V -B -e --no-transfer-progress \
+ ./mvnw -V -B -e --no-transfer-progress \
verify -Djdk.version=6 -Dbytecode.version=5 \
--toolchains=toolchains.xml
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..4cb0f7a85a
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+wrapperVersion=3.3.2
+distributionType=only-script
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000000..19529ddf8c
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,259 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.2
+#
+# Optional ENV vars
+# -----------------
+# JAVA_HOME - location of a JDK home dir, required when download maven via java source
+# MVNW_REPOURL - repo url base for downloading maven distribution
+# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+ [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+ native_path() { cygpath --path --windows "$1"; }
+ ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+ # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+ if [ -n "${JAVA_HOME-}" ]; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACCMD="$JAVA_HOME/jre/sh/javac"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ JAVACCMD="$JAVA_HOME/bin/javac"
+
+ if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+ echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+ echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+ return 1
+ fi
+ fi
+ else
+ JAVACMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v java
+ )" || :
+ JAVACCMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v javac
+ )" || :
+
+ if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+ echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+ return 1
+ fi
+ fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+ str="${1:-}" h=0
+ while [ -n "$str" ]; do
+ char="${str%"${str#?}"}"
+ h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+ str="${str#?}"
+ done
+ printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+ printf %s\\n "$1" >&2
+ exit 1
+}
+
+trim() {
+ # MWRAPPER-139:
+ # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+ # Needed for removing poorly interpreted newline sequences when running in more
+ # exotic environments such as mingw bash on Windows.
+ printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+ case "${key-}" in
+ distributionUrl) distributionUrl=$(trim "${value-}") ;;
+ distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+ esac
+done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+ MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+ case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+ *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+ :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+ :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+ :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+ *)
+ echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+ distributionPlatform=linux-amd64
+ ;;
+ esac
+ distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+ ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+ unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+ exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+ verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+ clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+ trap clean HUP INT TERM EXIT
+else
+ die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+ distributionUrl="${distributionUrl%.zip}.tar.gz"
+ distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+ verbose "Found wget ... using wget"
+ wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+ verbose "Found curl ... using curl"
+ curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+ verbose "Falling back to use Java to download"
+ javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+ targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+ cat >"$javaSource" <<-END
+ public class Downloader extends java.net.Authenticator
+ {
+ protected java.net.PasswordAuthentication getPasswordAuthentication()
+ {
+ return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+ }
+ public static void main( String[] args ) throws Exception
+ {
+ setDefault( new Downloader() );
+ java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+ }
+ }
+ END
+ # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+ verbose " - Compiling Downloader.java ..."
+ "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+ verbose " - Running Downloader.java ..."
+ "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+ distributionSha256Result=false
+ if [ "$MVN_CMD" = mvnd.sh ]; then
+ echo "Checksum validation is not supported for maven-mvnd." >&2
+ echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ elif command -v sha256sum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ elif command -v shasum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+ echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ fi
+ if [ $distributionSha256Result = false ]; then
+ echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+ echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+ unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000000..b150b91ed5
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,149 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.2
+@REM
+@REM Optional ENV vars
+@REM MVNW_REPOURL - repo url base for downloading maven distribution
+@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+ IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+ $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+ "maven-mvnd-*" {
+ $USE_MVND = $true
+ $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+ $MVN_CMD = "mvnd.cmd"
+ break
+ }
+ default {
+ $USE_MVND = $false
+ $MVN_CMD = $script -replace '^mvnw','mvn'
+ break
+ }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+if ($env:MVNW_REPOURL) {
+ $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
+if ($env:MAVEN_USER_HOME) {
+ $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
+}
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+ Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+ exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+ Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+ if ($TMP_DOWNLOAD_DIR.Exists) {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+ }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+ $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+ if ($USE_MVND) {
+ Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+ }
+ Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+ if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+ Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+ }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+ Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+ if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+ Write-Error "fail to move MAVEN_HOME"
+ }
+} finally {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
From 49ee4db49a3a0c4fdb0f376d729c064292fdc642 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Tue, 17 Sep 2024 06:47:44 +0200
Subject: [PATCH 054/163] Require at least Maven 3.9.9 for build (#1708)
---
.mvn/wrapper/maven-wrapper.properties | 2 +-
org.jacoco.build/pom.xml | 3 +-
org.jacoco.doc/docroot/doc/build.html | 62 ++++++++++-----------
org.jacoco.doc/docroot/doc/changes.html | 6 +-
org.jacoco.doc/docroot/doc/environment.html | 2 +-
5 files changed, 38 insertions(+), 37 deletions(-)
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index 4cb0f7a85a..d58dfb70ba 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -16,4 +16,4 @@
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index c28ccd159f..6a24dc0a69 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -519,8 +519,7 @@
17
-
- [3.6.3,3.8.2),(3.8.2,)
+ 3.9.9The rules for repo1.maven.org are that pom.xml files should not include repository definitions.
diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html
index efab7c1556..f524bdbce4 100644
--- a/org.jacoco.doc/docroot/doc/build.html
+++ b/org.jacoco.doc/docroot/doc/build.html
@@ -23,9 +23,8 @@
Build
The JaCoCo build is based on Maven and
can be locally executed on every machine with a proper
- environment setup. In particular you need at
- least Maven 3.6.3 and JDK 17
- installations. Developers are encouraged to run the build before every commit
+ environment setup. In particular you need JDK 17
+ installation. Developers are encouraged to run the build before every commit
to ensure consistency of the source tree.
@@ -33,12 +32,13 @@
Build
Running the Build
- The build can be started by executing the following command with
- ./org.jacoco.build/ as the working directory:
+ The build can be started by executing the
+ Maven Wrapper using following
+ command with ./org.jacoco.build/ as the working directory:
The JaCoCo build is based on Maven
- and requires at least Maven 3.6.3 and JDK 17.
+ and requires at least Maven 3.9.9 and JDK 17.
See the build description for details.
JaCoCo now officially supports Java 23
+ (GitHub #1757).
Calculation of line coverage for Kotlin inline functions
(GitHub #1670).
Calculation of line coverage for Kotlin inline functions
diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html
index 140a5e9f01..0bbb5c6d69 100644
--- a/org.jacoco.doc/docroot/doc/environment.html
+++ b/org.jacoco.doc/docroot/doc/environment.html
@@ -69,7 +69,7 @@
JRE/JDK
The minimum supported JRE version for JaCoCo is Java 5. To guarantee
compatibility JaCoCo release builds should always be executed using JDK 5.
In addition we run builds with 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
- 18, 19, 20, 21 and 22 JDKs.
+ 18, 19, 20, 21, 22 and 23 JDKs.
Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?
What Java versions are supported by JaCoCo?
- JaCoCo supports Java class files from version 1.0 to 22. However the minimum
+ JaCoCo supports Java class files from version 1.0 to 23. However the minimum
JRE version required by the JaCoCo runtime (e.g. the agent) and the JaCoCo
tools is 1.5. Also note that class files under test from version 1.6 and above
have to contain valid stackmap frames.
From 04d689e07e5613917d64a914d0bdf12477336a19 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 21 Oct 2024 09:33:26 +0000
Subject: [PATCH 083/163] Upgrade maven-javadoc-plugin to 3.10.1 (#1738)
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
org.jacoco.build/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index a870bd4b54..90ad9e6889 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -352,7 +352,7 @@
org.apache.maven.pluginsmaven-javadoc-plugin
- 3.10.0
+ 3.10.1truefalse
From 3a544915a86c7cbaf0b296c95c24322310c5a75b Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Tue, 22 Oct 2024 21:08:15 +0200
Subject: [PATCH 084/163] Upgrade maven-compiler-plugin to 3.12.1 (#1730)
---
.github/dependabot.yml | 6 ++++++
org.jacoco.build/pom.xml | 3 ++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index f49500be46..d5d2b4272d 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -23,6 +23,12 @@ updates:
# It is known that upgrade from current version requires additional changes:
- dependency-name: "org.apache.maven.plugins:maven-plugin-plugin"
- dependency-name: "org.apache.maven.plugins:maven-invoker-plugin"
+ # Because of
+ # https://github.com/apache/maven-compiler-plugin/blob/maven-compiler-plugin-3.13.0/pom.xml#L71
+ # https://github.com/codehaus-plexus/plexus-compiler/blob/plexus-compiler-2.15.0/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java#L149-L163
+ # requires javac version to be at least 6:
+ - dependency-name: "org.apache.maven.plugins:maven-compiler-plugin"
+ versions: ">=3.13.0"
# Requires tests to be executed with Java 6:
- dependency-name: "org.apache.maven.plugins:maven-surefire-plugin"
versions: ">=2.20.0"
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index 90ad9e6889..e41f899683 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -312,7 +312,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 3.11.0
+
+ 3.12.1org.apache.maven.plugins
From eef103a35387855e5a4157e0aceab1d4428b5dd1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 22 Oct 2024 22:34:05 +0200
Subject: [PATCH 085/163] Upgrade exec-maven-plugin to 3.5.0 (#1760)
Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.4.1...3.5.0)
---
updated-dependencies:
- dependency-name: org.codehaus.mojo:exec-maven-plugin
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
org.jacoco.build/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index e41f899683..f167167e3b 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -434,7 +434,7 @@
org.codehaus.mojoexec-maven-plugin
- 3.4.1
+ 3.5.0
From 1a6ad9dcd6fbeedfc7cb098f23b15e227ed1b275 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 29 Oct 2024 23:03:43 +0100
Subject: [PATCH 086/163] Bump actions/checkout from 4.2.1 to 4.2.2 (#1761)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871...11bd71901bbe5b1630ceea73d27597364c9af683)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eac5fb5c5a..4de0942972 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,7 +23,7 @@ jobs:
name: JDK ${{ matrix.jdk }}${{ matrix.ecj && ' with ECJ' || ''}}
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
with:
distribution: 'zulu'
@@ -58,7 +58,7 @@ jobs:
Windows:
runs-on: windows-2022
steps:
- - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
with:
distribution: 'zulu'
From d5908a249db6aa76b14f9661bc7f40e41ec7bc0c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 29 Oct 2024 22:33:26 +0000
Subject: [PATCH 087/163] Bump actions/setup-java from 4.4.0 to 4.5.0 (#1763)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/b36c23c0d998641eff861008f374ee103c25ac73...8df1039502a15bceb9433410b1a100fbe190c53b)
---
updated-dependencies:
- dependency-name: actions/setup-java
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4de0942972..089b7f2f39 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
+ - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
with:
distribution: 'zulu'
java-version: |
@@ -59,7 +59,7 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
+ - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
with:
distribution: 'zulu'
java-version: |
From bb9fdd670f2b5cf511520721461488cf1ecfc117 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 30 Oct 2024 09:49:41 +0000
Subject: [PATCH 088/163] Upgrade maven-dependency-plugin to 3.8.1 (#1762)
Bump org.apache.maven.plugins:maven-dependency-plugin
Bumps [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/apache/maven-dependency-plugin/releases)
- [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.8.0...maven-dependency-plugin-3.8.1)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-dependency-plugin
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
org.jacoco.build/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index f167167e3b..f074d89ad4 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -318,7 +318,7 @@
org.apache.maven.pluginsmaven-dependency-plugin
- 3.8.0
+ 3.8.1org.apache.maven.plugins
From 00312094ecf4ea543eeaf3beb7dcfdb932898405 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 8 Nov 2024 12:03:49 +0100
Subject: [PATCH 089/163] Add configuration files for Java code formatting in
IntelliJ IDEA (#1704)
* `.idea/externalDependencies.xml` to require installation of
EclipseCodeFormatter plugin into IntelliJ IDEA
* `.idea/eclipseCodeFormatter.xml` configures plugin to use
the same settings as for Eclipse IDE and spotelss-maven-plugin
* `.idea/codeStyles/codeStyleConfig.xml` and
`.idea/codeStyles/Project.xml` prevent use of wildcard imports
---
.idea/codeStyles/Project.xml | 8 ++++++++
.idea/codeStyles/codeStyleConfig.xml | 5 +++++
.idea/eclipseCodeFormatter.xml | 12 ++++++++++++
.idea/externalDependencies.xml | 6 ++++++
4 files changed, 31 insertions(+)
create mode 100644 .idea/codeStyles/Project.xml
create mode 100644 .idea/codeStyles/codeStyleConfig.xml
create mode 100644 .idea/eclipseCodeFormatter.xml
create mode 100644 .idea/externalDependencies.xml
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000000..a74a84d3a0
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000000..79ee123c2b
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/eclipseCodeFormatter.xml b/.idea/eclipseCodeFormatter.xml
new file mode 100644
index 0000000000..992c75f5c6
--- /dev/null
+++ b/.idea/eclipseCodeFormatter.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/externalDependencies.xml b/.idea/externalDependencies.xml
new file mode 100644
index 0000000000..0502dcf71c
--- /dev/null
+++ b/.idea/externalDependencies.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
From 11567593d0d1d5a9a5cc674baf4cf0e82c74966c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Nov 2024 22:12:38 +0000
Subject: [PATCH 090/163] Upgrade maven-javadoc-plugin to 3.11.1 (#1767)
Bump org.apache.maven.plugins:maven-javadoc-plugin in /org.jacoco.build
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
org.jacoco.build/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index f074d89ad4..f5f451e58d 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -353,7 +353,7 @@
org.apache.maven.pluginsmaven-javadoc-plugin
- 3.10.1
+ 3.11.1truefalse
From 7e3207484e2df256838186be8c7ed5c72e8f93ac Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Wed, 13 Nov 2024 07:59:28 +0100
Subject: [PATCH 091/163] Fix typo (#1775)
---
.../src/org/jacoco/core/internal/analysis/LineImplTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
index 1bba4f1109..fc35bd6293 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
@@ -20,7 +20,7 @@
import org.junit.Test;
/**
- * Unit tests for {@link LineImplTest}.
+ * Unit tests for {@link LineImpl}.
*/
public class LineImplTest {
From a69d52865f34cd5cb1b7a673c1b57282dea74dec Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 15 Nov 2024 12:48:00 +0100
Subject: [PATCH 092/163] Fix warning "'reportOutputDirectory' is unknown for
plugin 'maven-javadoc-plugin:3.11.1:jar (attach-javadocs)'" (#1776)
`reportOutputDirectory` parameter was removed in maven-javadoc-plugin
version 3.10.0 by
https://github.com/apache/maven-javadoc-plugin/commit/9638a6a76c6db53c3bf8ffbd5cec7318b0e25303
(https://issues.apache.org/jira/browse/MJAVADOC-785).
This was overlooked in commit 435579f27cb8259ba14c1a868245a843e053211f.
`outputDirectory` parameter can be used to restore prior behavior,
but this customization seems unnecessary.
---
org.jacoco.doc/pom.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml
index 6176308713..afd5f62766 100644
--- a/org.jacoco.doc/pom.xml
+++ b/org.jacoco.doc/pom.xml
@@ -198,7 +198,6 @@
jar
- ${project.build.directory}/apidocstrue*.internal.*,*.internal,org.jacoco.ant,org.jacoco.maven,org.jacoco.examples
From 3c44d5fd8d74f768301d9957237cf8db2052794b Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 15 Nov 2024 22:52:12 +0100
Subject: [PATCH 093/163] KotlinWhenFilter should handle nullable enums (#1774)
---
.../targets/KotlinWhenExpressionTarget.kt | 33 +++
.../analysis/filter/KotlinWhenFilterTest.java | 198 ++++++++++++++++++
.../analysis/filter/KotlinWhenFilter.java | 45 +++-
org.jacoco.doc/docroot/doc/changes.html | 4 +
4 files changed, 276 insertions(+), 4 deletions(-)
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
index ccf98244bb..6f5b004b5c 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
@@ -50,6 +50,27 @@ object KotlinWhenExpressionTarget {
else -> throw NoWhenBranchMatchedException() // assertEmpty()
} // assertFullyCovered()
+ private fun whenByNullableEnumWithNullCaseAndWithoutElse(e: Enum?): String =
+ when (e) { // assertFullyCovered(0, 3)
+ Enum.A -> "a" // assertFullyCovered()
+ Enum.B -> "b" // assertFullyCovered()
+ null -> "null" // assertFullyCovered()
+ } // assertFullyCovered()
+
+ private fun whenByNullableEnumWithoutNullCaseAndWithElse(e: Enum?): String =
+ when (e) { // assertFullyCovered(0, 3)
+ Enum.A -> "a" // assertFullyCovered()
+ Enum.B -> "b" // assertFullyCovered()
+ else -> "else" // assertFullyCovered()
+ } // assertFullyCovered()
+
+ private fun whenByNullableEnumWithNullAndElseCases(e: Enum?): String =
+ when (e) { // assertFullyCovered(0, 3)
+ Enum.A -> "a" // assertFullyCovered()
+ null -> "null" // assertFullyCovered()
+ else -> "else" // assertFullyCovered()
+ } // assertFullyCovered()
+
private fun whenString(p: String): Int = when (p) { // assertFullyCovered(0, 7)
"a" -> 1 // assertFullyCovered()
"b" -> 2 // assertFullyCovered()
@@ -88,6 +109,18 @@ object KotlinWhenExpressionTarget {
whenEnumRedundantElse(Enum.A)
whenEnumRedundantElse(Enum.B)
+ whenByNullableEnumWithNullCaseAndWithoutElse(Enum.A)
+ whenByNullableEnumWithNullCaseAndWithoutElse(Enum.B)
+ whenByNullableEnumWithNullCaseAndWithoutElse(null)
+
+ whenByNullableEnumWithoutNullCaseAndWithElse(Enum.A)
+ whenByNullableEnumWithoutNullCaseAndWithElse(Enum.B)
+ whenByNullableEnumWithoutNullCaseAndWithElse(null)
+
+ whenByNullableEnumWithNullAndElseCases(Enum.A)
+ whenByNullableEnumWithNullAndElseCases(Enum.B)
+ whenByNullableEnumWithNullAndElseCases(null)
+
whenString("")
whenString("a")
whenString("b")
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java
index bc366aac5a..77dcd4b583 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java
@@ -121,4 +121,202 @@ public void should_filter_implicit_default() {
assertReplacedBranches(switchNode, newTargets);
}
+ /**
+ *
+ * enum class E { A, B }
+ * fun example(e: E?) = when (e) {
+ * E.A -> "a"
+ * E.B -> "b"
+ * null -> "null"
+ * }
+ *
+ */
+ @Test
+ public void should_filter_when_by_nullable_enum_with_null_case_and_without_else() {
+ final Range range1 = new Range();
+ final Range range2 = new Range();
+ final HashSet newTargets = new HashSet();
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "example", "(LE;)Ljava/lang/String;", null, null);
+ final Label l1 = new Label();
+ final Label l2 = new Label();
+ final Label caseNull = new Label();
+ final Label caseElse = new Label();
+ final Label caseA = new Label();
+ final Label caseB = new Label();
+ final Label after = new Label();
+
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitInsn(Opcodes.DUP);
+ range1.fromInclusive = m.instructions.getLast();
+ m.visitJumpInsn(Opcodes.IFNONNULL, l1);
+ m.visitInsn(Opcodes.POP);
+ m.visitInsn(Opcodes.ICONST_M1);
+ m.visitJumpInsn(Opcodes.GOTO, l2);
+ m.visitLabel(l1);
+ m.visitFieldInsn(Opcodes.GETSTATIC, "ExampleKt$WhenMappings",
+ "$EnumSwitchMapping$0", "[I");
+ m.visitInsn(Opcodes.SWAP);
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "ExampleKt$Enum", "ordinal",
+ "()I", false);
+ m.visitInsn(Opcodes.IALOAD);
+ m.visitLabel(l2);
+ range1.toInclusive = m.instructions.getLast();
+ m.visitTableSwitchInsn(-1, 2, caseElse, caseNull, caseElse, caseA,
+ caseB);
+ final AbstractInsnNode switchNode = m.instructions.getLast();
+
+ m.visitLabel(caseA);
+ m.visitLdcInsn("a");
+ newTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseB);
+ m.visitLdcInsn("b");
+ newTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseNull);
+ m.visitLdcInsn("null");
+ newTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseElse);
+ range2.fromInclusive = m.instructions.getLast();
+ m.visitTypeInsn(Opcodes.NEW, "kotlin/NoWhenBranchMatchedException");
+ m.visitInsn(Opcodes.DUP);
+ m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "kotlin/NoWhenBranchMatchedException", "", "()V", false);
+ m.visitInsn(Opcodes.ATHROW);
+ range2.toInclusive = m.instructions.getLast();
+
+ m.visitLabel(after);
+ m.visitInsn(Opcodes.ARETURN);
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range1, range2);
+ assertReplacedBranches(switchNode, newTargets);
+ }
+
+ /**
+ *
+ * enum class E { A, B }
+ * fun example(e: E?) = when (e) {
+ * E.A -> "a"
+ * E.B -> "b"
+ * else -> "else"
+ * }
+ *
+ */
+ @Test
+ public void should_filter_when_by_nullable_enum_without_null_case_and_with_else() {
+ final Range range1 = new Range();
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "example", "(LE;)Ljava/lang/String;", null, null);
+ final Label l1 = new Label();
+ final Label l2 = new Label();
+ final Label caseElse = new Label();
+ final Label caseA = new Label();
+ final Label caseB = new Label();
+ final Label after = new Label();
+
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitInsn(Opcodes.DUP);
+ range1.fromInclusive = m.instructions.getLast();
+ m.visitJumpInsn(Opcodes.IFNONNULL, l1);
+ m.visitInsn(Opcodes.POP);
+ m.visitInsn(Opcodes.ICONST_M1);
+ m.visitJumpInsn(Opcodes.GOTO, l2);
+ m.visitLabel(l1);
+ m.visitFieldInsn(Opcodes.GETSTATIC, "ExampleKt$WhenMappings",
+ "$EnumSwitchMapping$0", "[I");
+ m.visitInsn(Opcodes.SWAP);
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "ExampleKt$Enum", "ordinal",
+ "()I", false);
+ m.visitInsn(Opcodes.IALOAD);
+ m.visitLabel(l2);
+ range1.toInclusive = m.instructions.getLast();
+ m.visitTableSwitchInsn(1, 2, caseElse, caseA, caseB);
+
+ m.visitLabel(caseA);
+ m.visitLdcInsn("a");
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseB);
+ m.visitLdcInsn("b");
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseElse);
+ m.visitLdcInsn("else");
+
+ m.visitLabel(after);
+ m.visitInsn(Opcodes.ARETURN);
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range1);
+ assertNoReplacedBranches();
+ }
+
+ /**
+ *
+ * enum class E { A, B }
+ * fun example(e: E?) = when (e) {
+ * E.A -> "a"
+ * null -> "null"
+ * else -> "else"
+ * }
+ *
+ */
+ @Test
+ public void should_filter_when_by_nullable_enum_with_null_and_else_cases() {
+ final Range range1 = new Range();
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "example", "(LE;)Ljava/lang/String;", null, null);
+ final Label l1 = new Label();
+ final Label l2 = new Label();
+ final Label caseNull = new Label();
+ final Label caseElse = new Label();
+ final Label caseA = new Label();
+ final Label after = new Label();
+
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitInsn(Opcodes.DUP);
+ range1.fromInclusive = m.instructions.getLast();
+ m.visitJumpInsn(Opcodes.IFNONNULL, l1);
+ m.visitInsn(Opcodes.POP);
+ m.visitInsn(Opcodes.ICONST_M1);
+ m.visitJumpInsn(Opcodes.GOTO, l2);
+ m.visitLabel(l1);
+ m.visitFieldInsn(Opcodes.GETSTATIC, "ExampleKt$WhenMappings",
+ "$EnumSwitchMapping$0", "[I");
+ m.visitInsn(Opcodes.SWAP);
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "ExampleKt$Enum", "ordinal",
+ "()I", false);
+ m.visitInsn(Opcodes.IALOAD);
+ m.visitLabel(l2);
+ range1.toInclusive = m.instructions.getLast();
+ m.visitTableSwitchInsn(-1, 1, caseElse, caseNull, caseA);
+
+ m.visitLabel(caseA);
+ m.visitLdcInsn("a");
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseNull);
+ m.visitLdcInsn("null");
+ m.visitJumpInsn(Opcodes.GOTO, after);
+
+ m.visitLabel(caseElse);
+ m.visitLdcInsn("else");
+
+ m.visitLabel(after);
+ m.visitInsn(Opcodes.ARETURN);
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range1);
+ assertNoReplacedBranches();
+ }
+
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
index 354161918e..202ed3bea6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
@@ -18,6 +18,7 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
@@ -26,9 +27,8 @@
/**
* Filters bytecode that Kotlin compiler generates for when
- * expressions which list all cases of enum or
- * sealed class, i.e. which don't require explicit
- * else.
+ * expressions and statements with subject of type enum class or
+ * sealed class.
*/
public final class KotlinWhenFilter implements IFilter {
@@ -39,6 +39,7 @@ public void filter(final MethodNode methodNode,
final Matcher matcher = new Matcher();
for (final AbstractInsnNode i : methodNode.instructions) {
matcher.match(i, output);
+ matcher.matchNullableEnum(i, output);
}
}
@@ -69,6 +70,39 @@ void match(final AbstractInsnNode start, final IFilterOutput output) {
}
}
}
+
+ void matchNullableEnum(final AbstractInsnNode start,
+ final IFilterOutput output) {
+ if (start.getOpcode() != Opcodes.DUP) {
+ return;
+ }
+ cursor = start;
+ // https://github.com/JetBrains/kotlin/blob/v2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/when/EnumSwitchCodegen.java#L46
+ nextIs(Opcodes.IFNONNULL);
+ final JumpInsnNode jump1 = (JumpInsnNode) cursor;
+ nextIs(Opcodes.POP);
+ nextIs(Opcodes.ICONST_M1);
+ nextIs(Opcodes.GOTO);
+ final JumpInsnNode jump2 = (JumpInsnNode) cursor;
+ nextIs(Opcodes.GETSTATIC);
+ final FieldInsnNode fieldInsnNode = (FieldInsnNode) cursor;
+ // https://github.com/JetBrains/kotlin/blob/v2.0.0/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java#L27-L28
+ if (fieldInsnNode == null
+ || !fieldInsnNode.owner.endsWith("$WhenMappings")
+ || !fieldInsnNode.name.startsWith("$EnumSwitchMapping$")) {
+ return;
+ }
+ nextIs(Opcodes.SWAP);
+ nextIs(Opcodes.INVOKEVIRTUAL); // ordinal()I
+ nextIs(Opcodes.IALOAD);
+ nextIsSwitch();
+ if (cursor != null
+ && skipNonOpcodes(jump1.label) == skipNonOpcodes(
+ jump2.getNext())
+ && skipNonOpcodes(jump2.label) == cursor) {
+ output.ignore(start, cursor.getPrevious());
+ }
+ }
}
private static LabelNode getDefaultLabel(final AbstractInsnNode i) {
@@ -90,9 +124,12 @@ private static void ignoreDefaultBranch(final AbstractInsnNode switchNode,
} else {
labels = ((TableSwitchInsnNode) switchNode).labels;
}
+ final LabelNode defaultLabel = getDefaultLabel(switchNode);
final Set newTargets = new HashSet();
for (final LabelNode label : labels) {
- newTargets.add(AbstractMatcher.skipNonOpcodes(label));
+ if (label != defaultLabel) {
+ newTargets.add(AbstractMatcher.skipNonOpcodes(label));
+ }
}
output.replaceBranches(switchNode, newTargets);
}
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 144fe37ec9..2a5caaa836 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -43,6 +43,10 @@
New Features
Part of bytecode generated by the Kotlin compiler for suspending lambdas
without suspension points is filtered out during generation of report
(GitHub #1283).
+
Part of bytecode generated by the Kotlin compiler for when
+ expressions and statements with nullable enum subject is filtered out during
+ generation of report
+ (GitHub #1774).
Method getEntries generated by the Kotlin compiler for enum
classes is filtered out during generation of report
(GitHub #1625).
From c533dedc7cc6d1408836059c01459a8487db6485 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sat, 16 Nov 2024 07:40:53 +0100
Subject: [PATCH 094/163] Fix typo (#1777)
---
.../src/org/jacoco/core/internal/flow/LabelInfo.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
index 48e813bd79..e3217d3e6d 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
@@ -119,7 +119,7 @@ public static void setMethodInvocationLine(final Label label) {
}
/**
- * Checks whether the a given label has been marked as a line with method
+ * Checks whether the given label has been marked as a line with method
* invocations.
*
* @param label
From 9368edebe136dba2477ad05a05873c08842f3b6b Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 18 Nov 2024 08:31:24 +0100
Subject: [PATCH 095/163] Split KotlinWhenExpressionTarget (#1778)
---
...ssionTest.java => KotlinWhenEnumTest.java} | 10 +--
.../kotlin/KotlinWhenSealedTest.java | 27 ++++++++
.../kotlin/KotlinWhenStringTest.java | 27 ++++++++
...ssionTarget.kt => KotlinWhenEnumTarget.kt} | 66 +------------------
.../kotlin/targets/KotlinWhenSealedTarget.kt | 46 +++++++++++++
.../kotlin/targets/KotlinWhenStringTarget.kt | 62 +++++++++++++++++
6 files changed, 169 insertions(+), 69 deletions(-)
rename org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/{KotlinWhenExpressionTest.java => KotlinWhenEnumTest.java} (77%)
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenSealedTest.java
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenStringTest.java
rename org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/{KotlinWhenExpressionTarget.kt => KotlinWhenEnumTarget.kt} (54%)
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenStringTarget.kt
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenEnumTest.java
similarity index 77%
rename from org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java
rename to org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenEnumTest.java
index 5bfe46d5d5..4aae895a46 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenEnumTest.java
@@ -13,15 +13,15 @@
package org.jacoco.core.test.validation.kotlin;
import org.jacoco.core.test.validation.ValidationTestBase;
-import org.jacoco.core.test.validation.kotlin.targets.KotlinWhenExpressionTarget;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinWhenEnumTarget;
/**
- * Test of when expressions.
+ * Test of code coverage in {@link KotlinWhenEnumTarget}.
*/
-public class KotlinWhenExpressionTest extends ValidationTestBase {
+public class KotlinWhenEnumTest extends ValidationTestBase {
- public KotlinWhenExpressionTest() {
- super(KotlinWhenExpressionTarget.class);
+ public KotlinWhenEnumTest() {
+ super(KotlinWhenEnumTarget.class);
}
}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenSealedTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenSealedTest.java
new file mode 100644
index 0000000000..25424b0dd6
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenSealedTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinWhenSealedTarget;
+
+/**
+ * Test of code coverage in {@link KotlinWhenSealedTarget}.
+ */
+public class KotlinWhenSealedTest extends ValidationTestBase {
+
+ public KotlinWhenSealedTest() {
+ super(KotlinWhenSealedTarget.class);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenStringTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenStringTest.java
new file mode 100644
index 0000000000..404931faba
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenStringTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinWhenStringTarget;
+
+/**
+ * Test of code coverage in {@link KotlinWhenStringTarget}.
+ */
+public class KotlinWhenStringTest extends ValidationTestBase {
+
+ public KotlinWhenStringTest() {
+ super(KotlinWhenStringTarget.class);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenEnumTarget.kt
similarity index 54%
rename from org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
rename to org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenEnumTarget.kt
index 6f5b004b5c..5983d5b3ce 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenEnumTarget.kt
@@ -13,26 +13,9 @@
package org.jacoco.core.test.validation.kotlin.targets
/**
- * This test target is `when` expression.
+ * Test target with `when` expressions with subject of type `enum class`.
*/
-object KotlinWhenExpressionTarget {
-
- private sealed class Sealed {
- object Sealed1 : Sealed()
- object Sealed2 : Sealed()
- }
-
- private fun whenSealed(p: Sealed): Int = when (p) { // assertFullyCovered()
- is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
- is Sealed.Sealed2 -> 2 // assertFullyCovered()
- } // assertFullyCovered()
-
- @Suppress("REDUNDANT_ELSE_IN_WHEN")
- private fun whenSealedRedundantElse(p: Sealed): Int = when (p) { // assertFullyCovered()
- is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
- is Sealed.Sealed2 -> 2 // assertFullyCovered(0, 0)
- else -> throw NoWhenBranchMatchedException() // assertEmpty()
- } // assertFullyCovered()
+object KotlinWhenEnumTarget {
private enum class Enum {
A, B
@@ -71,38 +54,8 @@ object KotlinWhenExpressionTarget {
else -> "else" // assertFullyCovered()
} // assertFullyCovered()
- private fun whenString(p: String): Int = when (p) { // assertFullyCovered(0, 7)
- "a" -> 1 // assertFullyCovered()
- "b" -> 2 // assertFullyCovered()
- "c" -> 3 // assertFullyCovered()
- "\u0000a" -> 4 // assertFullyCovered()
- "\u0000b" -> 5 // assertFullyCovered()
- "\u0000c" -> 6 // assertFullyCovered()
- else -> 7 // assertFullyCovered()
- } // assertFullyCovered()
-
- /**
- * Unlike [whenString]
- * in this example first case is the only case with biggest hashCode value.
- * FIXME https://github.com/jacoco/jacoco/issues/1295
- */
- private fun whenStringBiggestHashCodeFirst(p: String): Int = when (p) { // assertPartlyCovered(3, 11)
- "c" -> 1 // assertFullyCovered()
- "b" -> 2 // assertFullyCovered()
- "\u0000b" -> 3 // assertFullyCovered()
- "a" -> 4 // assertFullyCovered()
- "\u0000a" -> 5 // assertFullyCovered()
- else -> 6 // assertFullyCovered()
- } // assertFullyCovered()
-
@JvmStatic
fun main(args: Array) {
- whenSealed(Sealed.Sealed1)
- whenSealed(Sealed.Sealed2)
-
- whenSealedRedundantElse(Sealed.Sealed1)
- whenSealedRedundantElse(Sealed.Sealed2)
-
whenEnum(Enum.A)
whenEnum(Enum.B)
@@ -120,21 +73,6 @@ object KotlinWhenExpressionTarget {
whenByNullableEnumWithNullAndElseCases(Enum.A)
whenByNullableEnumWithNullAndElseCases(Enum.B)
whenByNullableEnumWithNullAndElseCases(null)
-
- whenString("")
- whenString("a")
- whenString("b")
- whenString("c")
- whenString("\u0000a")
- whenString("\u0000b")
- whenString("\u0000c")
-
- whenStringBiggestHashCodeFirst("")
- whenStringBiggestHashCodeFirst("a")
- whenStringBiggestHashCodeFirst("b")
- whenStringBiggestHashCodeFirst("c")
- whenStringBiggestHashCodeFirst("\u0000a")
- whenStringBiggestHashCodeFirst("\u0000b")
}
}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
new file mode 100644
index 0000000000..12ec77ab52
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target with `when` expressions with subject of type `enum class`.
+ */
+object KotlinWhenSealedTarget {
+
+ private sealed class Sealed {
+ object Sealed1 : Sealed()
+ object Sealed2 : Sealed()
+ }
+
+ private fun whenSealed(p: Sealed): Int = when (p) { // assertFullyCovered()
+ is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
+ is Sealed.Sealed2 -> 2 // assertFullyCovered()
+ } // assertFullyCovered()
+
+ @Suppress("REDUNDANT_ELSE_IN_WHEN")
+ private fun whenSealedRedundantElse(p: Sealed): Int = when (p) { // assertFullyCovered()
+ is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
+ is Sealed.Sealed2 -> 2 // assertFullyCovered(0, 0)
+ else -> throw NoWhenBranchMatchedException() // assertEmpty()
+ } // assertFullyCovered()
+
+ @JvmStatic
+ fun main(args: Array) {
+ whenSealed(Sealed.Sealed1)
+ whenSealed(Sealed.Sealed2)
+
+ whenSealedRedundantElse(Sealed.Sealed1)
+ whenSealedRedundantElse(Sealed.Sealed2)
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenStringTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenStringTarget.kt
new file mode 100644
index 0000000000..234c141221
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenStringTarget.kt
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target with `when` expressions with subject of type `String`.
+ */
+object KotlinWhenStringTarget {
+
+ private fun whenString(p: String): Int = when (p) { // assertFullyCovered(0, 7)
+ "a" -> 1 // assertFullyCovered()
+ "b" -> 2 // assertFullyCovered()
+ "c" -> 3 // assertFullyCovered()
+ "\u0000a" -> 4 // assertFullyCovered()
+ "\u0000b" -> 5 // assertFullyCovered()
+ "\u0000c" -> 6 // assertFullyCovered()
+ else -> 7 // assertFullyCovered()
+ } // assertFullyCovered()
+
+ /**
+ * Unlike [whenString]
+ * in this example first case is the only case with biggest hashCode value.
+ * FIXME https://github.com/jacoco/jacoco/issues/1295
+ */
+ private fun whenStringBiggestHashCodeFirst(p: String): Int = when (p) { // assertPartlyCovered(3, 11)
+ "c" -> 1 // assertFullyCovered()
+ "b" -> 2 // assertFullyCovered()
+ "\u0000b" -> 3 // assertFullyCovered()
+ "a" -> 4 // assertFullyCovered()
+ "\u0000a" -> 5 // assertFullyCovered()
+ else -> 6 // assertFullyCovered()
+ } // assertFullyCovered()
+
+ @JvmStatic
+ fun main(args: Array) {
+ whenString("")
+ whenString("a")
+ whenString("b")
+ whenString("c")
+ whenString("\u0000a")
+ whenString("\u0000b")
+ whenString("\u0000c")
+
+ whenStringBiggestHashCodeFirst("")
+ whenStringBiggestHashCodeFirst("a")
+ whenStringBiggestHashCodeFirst("b")
+ whenStringBiggestHashCodeFirst("c")
+ whenStringBiggestHashCodeFirst("\u0000a")
+ whenStringBiggestHashCodeFirst("\u0000b")
+ }
+
+}
From f34c838f1c31531b60d905607f35d531ddaacae1 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 18 Nov 2024 09:00:28 +0100
Subject: [PATCH 096/163] Validation tests should create ASMified and TEXTified
bytecode representations (#1770)
---
.../test/validation/ValidationTestBase.java | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
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 50ccd23e15..e3417a3d7a 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
@@ -17,6 +17,7 @@
import java.io.File;
import java.io.IOException;
+import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,6 +44,10 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runners.model.MultipleFailureException;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.util.ASMifier;
+import org.objectweb.asm.util.Textifier;
+import org.objectweb.asm.util.TraceClassVisitor;
/**
* Base class for validation tests. It executes the given class under code
@@ -107,6 +112,23 @@ private void analyze(final Analyzer analyzer, final ExecutionData data)
final byte[] bytes = TargetLoader
.getClassDataAsBytes(target.getClassLoader(), data.getName());
analyzer.analyzeClass(bytes, data.getName());
+ saveBytecodeRepresentations(bytes, data.getName());
+ }
+
+ private void saveBytecodeRepresentations(final byte[] classBytes,
+ final String className) throws IOException {
+ final File outputDir = new File("target/asm/" + target.getSimpleName());
+ outputDir.mkdirs();
+ final String fileName = className.replace('/', '.');
+ final PrintWriter textWriter = new PrintWriter(
+ new File(outputDir, fileName + ".txt"));
+ final PrintWriter asmWriter = new PrintWriter(
+ new File(outputDir, fileName + ".java"));
+ new ClassReader(classBytes).accept(new TraceClassVisitor(
+ new TraceClassVisitor(null, new Textifier(), textWriter),
+ new ASMifier(), asmWriter), 0);
+ textWriter.close();
+ asmWriter.close();
}
/**
From 1e8b179cc08dc00f8507b67db6582861fe3068f5 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Wed, 20 Nov 2024 08:24:40 +0100
Subject: [PATCH 097/163] Fix typo: replace "a instrumented" by "an
instrumented" (#1781)
"an" should be used instead of "a" when the
following word starts with a vowel sound.
---
.../core/test/perf/ExecuteInstrumentedCodeScenario.java | 2 +-
.../src/org/jacoco/core/instr/Instrumenter.java | 8 ++++----
.../org/jacoco/core/internal/instr/ClassInstrumenter.java | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
index 0bd610fd98..54e455ab7d 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
@@ -22,7 +22,7 @@
/**
* This scenario runs a given scenario twice and reports the execution time:
- * Once on its original version, once in a instrumented version.
+ * Once on its original version, once in an instrumented version.
*/
public class ExecuteInstrumentedCodeScenario extends TimedScenario {
diff --git a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
index 7aaa4bb9d0..0b78892373 100644
--- a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
+++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
@@ -93,7 +93,7 @@ protected String getCommonSuperClass(final String type1,
}
/**
- * Creates a instrumented version of the given class if possible.
+ * Creates an instrumented version of the given class if possible.
*
* @param buffer
* definition of the class
@@ -113,7 +113,7 @@ public byte[] instrument(final byte[] buffer, final String name)
}
/**
- * Creates a instrumented version of the given class if possible. The
+ * Creates an instrumented version of the given class if possible. The
* provided {@link InputStream} is not closed by this method.
*
* @param input
@@ -137,7 +137,7 @@ public byte[] instrument(final InputStream input, final String name)
}
/**
- * Creates a instrumented version of the given class file. The provided
+ * Creates an instrumented version of the given class file. The provided
* {@link InputStream} and {@link OutputStream} instances are not closed by
* this method.
*
@@ -166,7 +166,7 @@ private IOException instrumentError(final String name,
}
/**
- * Creates a instrumented version of the given resource depending on its
+ * Creates an instrumented version of the given resource depending on its
* type. Class files and the content of archive files are instrumented. All
* other files are copied without modification. The provided
* {@link InputStream} and {@link OutputStream} instances are not closed by
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
index ff76b441c6..52847b2370 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
@@ -28,7 +28,7 @@ public class ClassInstrumenter extends ClassProbesVisitor {
private String className;
/**
- * Emits a instrumented version of this class to the given class visitor.
+ * Emits an instrumented version of this class to the given class visitor.
*
* @param probeArrayStrategy
* this strategy will be used to access the probe array
From 20f076cb921588b80e6bb0b397b9aaf4dde910b5 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Wed, 20 Nov 2024 20:49:24 +0100
Subject: [PATCH 098/163] Fix typo: replace "an child" by "a child" (#1782)
"a" should be used instead of "an" when the
following word doesn't start with a vowel sound.
---
.../src/org/jacoco/report/internal/xml/XMLElement.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
index 7908970c90..950b377647 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
@@ -157,7 +157,7 @@ private void quote(final String text) throws IOException {
}
/**
- * Adds an attribute to this element. May only be called before an child
+ * Adds an attribute to this element. May only be called before a child
* element is added or this element has been closed. The attribute value
* will be quoted. If the value is null the attribute will not
* be added.
@@ -188,7 +188,7 @@ public final void attr(final String name, final String value)
}
/**
- * Adds an attribute to this element. May only be called before an child
+ * Adds an attribute to this element. May only be called before a child
* element is added or this element has been closed. The attribute value is
* the decimal representation of the given int value.
*
@@ -206,7 +206,7 @@ public final void attr(final String name, final int value)
}
/**
- * Adds an attribute to this element. May only be called before an child
+ * Adds an attribute to this element. May only be called before a child
* element is added or this element has been closed. The attribute value is
* the decimal representation of the given long value.
*
From 764b1d1026c9dc58028cfbb03a90f6048135ffcf Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Thu, 21 Nov 2024 06:50:12 +0100
Subject: [PATCH 099/163] Fix typo (#1783)
---
.../src/org/jacoco/report/internal/html/page/SessionsPage.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
index a51c3f7680..4ec8ad08d0 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
@@ -54,7 +54,7 @@ public class SessionsPage extends ReportPage {
private final ElementIndex index;
/**
- * Creates a new page page to display session information.
+ * Creates a new page to display session information.
*
* @param sessionInfos
* session info objects
From ed3cb650e1dd477fcdf8a74e799b60825e5a98a3 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Thu, 21 Nov 2024 21:43:21 +0100
Subject: [PATCH 100/163] Build should not produce warning about generation of
JUnit report (#1784)
---
org.jacoco.doc/pom.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml
index afd5f62766..cd4f5c1df1 100644
--- a/org.jacoco.doc/pom.xml
+++ b/org.jacoco.doc/pom.xml
@@ -157,7 +157,6 @@
-
From e68ecf2385522009dc74dace96037f8d90be311e Mon Sep 17 00:00:00 2001
From: "Marc R. Hoffmann"
Date: Thu, 21 Nov 2024 22:50:50 +0100
Subject: [PATCH 101/163] Do not test with SecurityManager when Java version 24
and above (#1780)
Co-authored-by: Evgeny Mandrikov
---
org.jacoco.ant.test/pom.xml | 4 ++
.../src/org/jacoco/ant/CoverageTaskTest.xml | 16 -------
.../src/org/jacoco/ant/InstrumentTaskTest.xml | 10 ++---
.../org/jacoco/ant/SecurityManagerTest.java | 41 ++++++++++++++++++
.../org/jacoco/ant/SecurityManagerTest.xml | 43 +++++++++++++++++++
.../src/org/jacoco/ant/empty.xml | 17 ++++++++
6 files changed, 110 insertions(+), 21 deletions(-)
create mode 100644 org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.java
create mode 100644 org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
create mode 100644 org.jacoco.ant.test/src/org/jacoco/ant/empty.xml
diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml
index 0decb5008b..8e33b6e2f2 100644
--- a/org.jacoco.ant.test/pom.xml
+++ b/org.jacoco.ant.test/pom.xml
@@ -33,6 +33,10 @@
${project.groupId}org.jacoco.ant
+
+ ${project.groupId}
+ org.jacoco.core.test
+ junitjunit
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
index a4024d2ea7..3c7308632a 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
@@ -166,20 +166,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
index 8046900240..6fea583c16 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
@@ -63,7 +63,7 @@
-
+
@@ -84,7 +84,7 @@
-
+
@@ -95,7 +95,7 @@
-
+ destfile=test.exec
@@ -112,7 +112,7 @@
-
+
@@ -129,7 +129,7 @@
-
+
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.java
new file mode 100644
index 0000000000..ef9207cef7
--- /dev/null
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.ant;
+
+import java.io.File;
+
+import org.apache.ant.antunit.junit3.AntUnitSuite;
+import org.apache.ant.antunit.junit4.AntUnitSuiteRunner;
+import org.jacoco.core.test.validation.JavaVersion;
+import org.junit.runner.RunWith;
+
+import junit.framework.TestSuite;
+
+@RunWith(AntUnitSuiteRunner.class)
+public class SecurityManagerTest {
+
+ public static TestSuite suite() {
+ if (JavaVersion.current().isBefore("24")) {
+ System.setProperty("org.jacoco.ant.securityManagerTest.classes.dir",
+ TestTarget.getClassPath());
+ final File file = new File(
+ "src/org/jacoco/ant/SecurityManagerTest.xml");
+ return new AntUnitSuite(file, SecurityManagerTest.class);
+ }
+ // Ability to enable Security Manager was removed in Java 24
+ // https://openjdk.org/jeps/486
+ final File file = new File("src/org/jacoco/ant/empty.xml");
+ return new AntUnitSuite(file, SecurityManagerTest.class);
+ }
+
+}
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
new file mode 100644
index 0000000000..0ce62cffac
--- /dev/null
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/empty.xml b/org.jacoco.ant.test/src/org/jacoco/ant/empty.xml
new file mode 100644
index 0000000000..70a5a1dded
--- /dev/null
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/empty.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
From 92936c51fb3572f77a4eca9a2c1775afb7580dfa Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 22 Nov 2024 08:22:26 +0100
Subject: [PATCH 102/163] SecurityManagerTest should not depend on
CoverageTaskTest (#1785)
---
org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
index 0ce62cffac..beec33cd44 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/SecurityManagerTest.xml
@@ -27,7 +27,7 @@
-
+
From a1571a8d82b0a99df2131dfdfd6749605fee93db Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 22 Nov 2024 09:07:07 +0100
Subject: [PATCH 103/163] Fix typo: replace "a instance" by "an instance"
(#1786)
"an" should be used instead of "a" when the
following word starts with a vowel sound.
---
.../src/org/jacoco/core/data/ExecutionDataStore.java | 2 +-
.../core/internal/analysis/MethodCoverageCalculator.java | 6 +++---
.../src/org/jacoco/report/internal/xml/XMLElement.java | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
index 0b62309d4a..b6aad5268f 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
@@ -24,7 +24,7 @@
* {@link IExecutionDataVisitor} interface. If execution data is provided
* multiple times for the same class the data is merged, i.e. a probe is marked
* as executed if it is reported as executed at least once. This allows to merge
- * coverage date from multiple runs. A instance of this class is not thread
+ * coverage date from multiple runs. An instance of this class is not thread
* safe.
*/
public final class ExecutionDataStore implements IExecutionDataVisitor {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java
index 2c7dec6dac..1e0bbe4e5c 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java
@@ -25,9 +25,9 @@
import org.objectweb.asm.tree.AbstractInsnNode;
/**
- * Calculates the filtered coverage of a single method. A instance of this class
- * can be first used as {@link IFilterOutput} before the coverage result is
- * calculated.
+ * Calculates the filtered coverage of a single method. An instance of this
+ * class can be first used as {@link IFilterOutput} before the coverage result
+ * is calculated.
*/
class MethodCoverageCalculator implements IFilterOutput {
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
index 950b377647..4ecfdfcc05 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
@@ -246,7 +246,7 @@ public final void text(final String text) throws IOException {
/**
* Creates a new child element for this element. Might be overridden in
- * subclasses to return a instance of the subclass.
+ * subclasses to return an instance of the subclass.
*
* @param name
* name of the child element
From 91bf76cbbbd42d733e6b8bef7a094a01ecaccd74 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 22 Nov 2024 20:50:48 +0100
Subject: [PATCH 104/163] Fix typo: replace "an listener" by "a listener"
(#1789)
"a" should be used instead of "an" when the
following word doesn't start with a vowel sound.
---
.../src/org/jacoco/core/data/ExecutionDataReader.java | 4 ++--
.../src/org/jacoco/core/runtime/RemoteControlReader.java | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
index f30a3c4d74..0f7aaf79a3 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
@@ -46,7 +46,7 @@ public ExecutionDataReader(final InputStream input) {
}
/**
- * Sets an listener for session information.
+ * Sets a listener for session information.
*
* @param visitor
* visitor to retrieve session info events
@@ -56,7 +56,7 @@ public void setSessionInfoVisitor(final ISessionInfoVisitor visitor) {
}
/**
- * Sets an listener for execution data.
+ * Sets a listener for execution data.
*
* @param visitor
* visitor to retrieve execution data events
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
index d5b9c81785..7f4ff118db 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
@@ -50,7 +50,7 @@ protected boolean readBlock(final byte blockid) throws IOException {
}
/**
- * Sets an listener for agent commands.
+ * Sets a listener for agent commands.
*
* @param visitor
* visitor to retrieve agent commands
From 1d9f0bb2ec7bcf7c68466e43d911ab7b58fe2817 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 22 Nov 2024 22:19:58 +0100
Subject: [PATCH 105/163] Fix javadoc doclint warning "no @param for fragment"
(#1788)
This was overlooked in commit 831ecd609e17a3a5f8e114134fa0ce1d2071c6bd.
---
.../src/org/jacoco/core/internal/analysis/SourceNodeImpl.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
index bab8b9edfd..44149c62f1 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
@@ -42,6 +42,8 @@ public SourceNodeImpl(final ElementType elementType, final String name) {
}
/**
+ * @param fragment
+ * fragment to apply
* @return true if fragment contains lines of this node
*/
public boolean applyFragment(final SourceNodeImpl fragment) {
From 10705517b5d9a0bc8c8a9d3386c84adc0740112c Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 00:07:45 +0100
Subject: [PATCH 106/163] Add validation test for Kotlin `when` statement with
`sealed class` subject type (#1791)
---
.../kotlin/targets/KotlinWhenSealedTarget.kt | 73 +++++++++++++++----
1 file changed, 60 insertions(+), 13 deletions(-)
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
index 12ec77ab52..0b3b3d87ec 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenSealedTarget.kt
@@ -12,8 +12,10 @@
*******************************************************************************/
package org.jacoco.core.test.validation.kotlin.targets
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
/**
- * Test target with `when` expressions with subject of type `enum class`.
+ * Test target with `when` expressions and statements with subject of type `sealed class`.
*/
object KotlinWhenSealedTarget {
@@ -22,25 +24,70 @@ object KotlinWhenSealedTarget {
object Sealed2 : Sealed()
}
- private fun whenSealed(p: Sealed): Int = when (p) { // assertFullyCovered()
- is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
- is Sealed.Sealed2 -> 2 // assertFullyCovered()
- } // assertFullyCovered()
+ private fun expression(sealed: Sealed): String =
+ when (sealed) { // assertFullyCovered()
+ is Sealed.Sealed1 -> "case 1" // assertFullyCovered(0, 2)
+ is Sealed.Sealed2 -> "case 2" // assertFullyCovered()
+ } // assertFullyCovered()
@Suppress("REDUNDANT_ELSE_IN_WHEN")
- private fun whenSealedRedundantElse(p: Sealed): Int = when (p) { // assertFullyCovered()
- is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
- is Sealed.Sealed2 -> 2 // assertFullyCovered(0, 0)
- else -> throw NoWhenBranchMatchedException() // assertEmpty()
+ private fun expressionWithRedundantElse(sealed: Sealed): String =
+ when (sealed) { // assertFullyCovered()
+ is Sealed.Sealed1 -> "case 1" // assertFullyCovered(0, 2)
+ is Sealed.Sealed2 -> "case 2" // assertFullyCovered(0, 0)
+ else -> throw NoWhenBranchMatchedException() // assertEmpty()
+ } // assertFullyCovered()
+
+ /**
+ * Since Kotlin 1.7 `when` statement with subject of type `sealed class`
+ * must be exhaustive (error otherwise, warning in 1.6), however
+ * Kotlin compiler prior to version 2.0 was generating bytecode
+ * indistinguishable from [nonSealedWhen] and [nonSealedIf]
+ * that do not have coverage for the case of [NonSealed.NonSealed3].
+ */
+ private fun statement(sealed: Sealed) { // assertEmpty()
+ when (sealed) { // assertFullyCovered()
+ is Sealed.Sealed1 -> nop("case 1") // assertFullyCovered(0, 2)
+ is Sealed.Sealed2 -> nop("case 2") // assertFullyCovered()
+ } // assertEmpty()
+ } // assertFullyCovered()
+
+ private abstract class NonSealed {
+ class NonSealed1 : NonSealed()
+ class NonSealed2 : NonSealed()
+ class NonSealed3 : NonSealed()
+ }
+
+ private fun nonSealedWhen(nonSealed: NonSealed) { // assertEmpty()
+ when (nonSealed) { // assertFullyCovered()
+ is NonSealed.NonSealed1 -> nop("case 1") // assertFullyCovered(0, 2)
+ is NonSealed.NonSealed2 -> nop("case 2") // assertFullyCovered(1, 1)
+ /* missing is NonSealed.NonSealed3 */
+ } // assertEmpty()
+ } // assertFullyCovered()
+
+ private fun nonSealedIf(nonSealed: NonSealed) { // assertEmpty()
+ if (nonSealed is NonSealed.NonSealed1) nop("case 1") // assertFullyCovered(0, 2)
+ else if (nonSealed is NonSealed.NonSealed2) nop("case 2") // assertFullyCovered(1, 1)
+ /* missing is NonSealed.NonSealed3 */
} // assertFullyCovered()
@JvmStatic
fun main(args: Array) {
- whenSealed(Sealed.Sealed1)
- whenSealed(Sealed.Sealed2)
+ expression(Sealed.Sealed1)
+ expression(Sealed.Sealed2)
+
+ expressionWithRedundantElse(Sealed.Sealed1)
+ expressionWithRedundantElse(Sealed.Sealed2)
+
+ statement(Sealed.Sealed1)
+ statement(Sealed.Sealed2)
+
+ nonSealedWhen(NonSealed.NonSealed1())
+ nonSealedWhen(NonSealed.NonSealed2())
- whenSealedRedundantElse(Sealed.Sealed1)
- whenSealedRedundantElse(Sealed.Sealed2)
+ nonSealedIf(NonSealed.NonSealed1())
+ nonSealedIf(NonSealed.NonSealed2())
}
}
From 0ebc1d93eb58b451dae75c5825647fef270f70e5 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 08:46:09 +0100
Subject: [PATCH 107/163] Fix typo: replace "a XML" by "an XML" (#1790)
"an" should be used instead of "a" when the
following word starts with a vowel sound.
---
org.jacoco.doc/docroot/doc/ant.html | 2 +-
.../src/org/jacoco/report/internal/xml/ReportElement.java | 2 +-
.../src/org/jacoco/report/internal/xml/XMLElement.java | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/org.jacoco.doc/docroot/doc/ant.html b/org.jacoco.doc/docroot/doc/ant.html
index f0ddfd58f5..1b1b37e39c 100644
--- a/org.jacoco.doc/docroot/doc/ant.html
+++ b/org.jacoco.doc/docroot/doc/ant.html
@@ -89,7 +89,7 @@
Prerequisites
- Declaring a XML namespace for JaCoCo tasks is optional but always recommended
+ Declaring an XML namespace for JaCoCo tasks is optional but always recommended
if you mix tasks from different libraries. All subsequent examples use the
jacoco prefix declared above. If you don't declare a separate
namespace the jacoco prefix must be removed from the following
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
index 3e35fc129b..18fbd735f8 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
@@ -32,7 +32,7 @@ public class ReportElement extends XMLElement {
private static final String SYSTEM = "report.dtd";
/**
- * Creates a report root element for a XML report.
+ * Creates a report root element for an XML report.
*
* @param name
* value for the name attribute
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
index 4ecfdfcc05..3e527906fa 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
@@ -20,8 +20,8 @@
import java.io.Writer;
/**
- * Simple API to create well formed XML streams with minimal memory overhead. A
- * {@link XMLElement} instance represents a single element in a XML document.
+ * Simple API to create well formed XML streams with minimal memory overhead. An
+ * {@link XMLElement} instance represents a single element in an XML document.
* {@link XMLElement} can be used directly or might be subclassed for schema
* specific convenience methods.
*/
@@ -60,7 +60,7 @@ private XMLElement(final Writer writer, final String name,
}
/**
- * Creates a root element of a XML document.
+ * Creates a root element of an XML document.
*
* @param name
* element name
@@ -95,7 +95,7 @@ public XMLElement(final String name, final String pubId,
}
/**
- * Creates a new child element within a XML document. May only be called
+ * Creates a new child element within an XML document. May only be called
* before the parent element has been closed.
*
* @param name
From e1340eb7a6d96a5f1fd0dc2337b35bbc94220589 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 11:56:14 +0100
Subject: [PATCH 108/163] Add unit test for LocalProbeArrayStrategy (#1792)
---
.../instr/LocalProbeArrayStrategyTest.java | 73 +++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategyTest.java
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategyTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategyTest.java
new file mode 100644
index 0000000000..7a4ce363b8
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategyTest.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.instr;
+
+import static org.junit.Assert.assertEquals;
+
+import org.jacoco.core.instr.MethodRecorder;
+import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.ClassNode;
+
+/**
+ * Unit tests for {@link LocalProbeArrayStrategy}.
+ */
+public class LocalProbeArrayStrategyTest {
+
+ private LocalProbeArrayStrategy strategy;
+
+ @Before
+ public void setup() {
+ strategy = new LocalProbeArrayStrategy("ClassName", 1L, 2,
+ new IExecutionDataAccessorGenerator() {
+ public int generateDataAccessor(final long classid,
+ final String classname, final int probecount,
+ final MethodVisitor mv) {
+ assertEquals(1L, classid);
+ assertEquals(2, probecount);
+ assertEquals("ClassName", classname);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "Runtime",
+ "getProbes", "()[Z", false);
+ return 42;
+ }
+ });
+ }
+
+ @Test
+ public void should_store_instance() {
+ final MethodRecorder actualMethod = new MethodRecorder();
+ final int maxStack = strategy.storeInstance(actualMethod.getVisitor(),
+ false, 13);
+ assertEquals(42, maxStack);
+
+ final MethodRecorder expectedMethod = new MethodRecorder();
+ final MethodVisitor expected = expectedMethod.getVisitor();
+ expected.visitMethodInsn(Opcodes.INVOKESTATIC, "Runtime", "getProbes",
+ "()[Z", false);
+ expected.visitVarInsn(Opcodes.ASTORE, 13);
+ assertEquals(expectedMethod, actualMethod);
+ }
+
+ @Test
+ public void should_not_add_members() {
+ final ClassNode c = new ClassNode();
+ strategy.addMembers(c, 0);
+
+ assertEquals(0, c.methods.size());
+ assertEquals(0, c.fields.size());
+ }
+
+}
From 667655df85737199a0942943027c80e845a90aae Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 12:26:41 +0100
Subject: [PATCH 109/163] Fix typo: replace "a HTML" by "an HTML" (#1793)
"an" should be used instead of "a" when the
following word starts with a vowel sound.
---
.../src/org/jacoco/examples/ReportGenerator.java | 2 +-
.../src/org/jacoco/report/internal/html/IHTMLReportContext.java | 2 +-
.../src/org/jacoco/report/internal/html/index/ElementIndex.java | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java b/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
index 4aa3a0a86f..e63b5b051a 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
@@ -25,7 +25,7 @@
import org.jacoco.report.html.HTMLFormatter;
/**
- * This example creates a HTML report for eclipse like projects based on a
+ * This example creates an HTML report for eclipse like projects based on a
* single execution data store called jacoco.exec. The report contains no
* grouping information.
*
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java b/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
index 5ea660791f..8fbd97424b 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
@@ -20,7 +20,7 @@
import org.jacoco.report.internal.html.table.Table;
/**
- * Context and configuration information during creation of a HTML report.
+ * Context and configuration information during creation of an HTML report.
*/
public interface IHTMLReportContext {
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
index b72b8cd440..3721204dac 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
@@ -29,7 +29,7 @@ public class ElementIndex implements IIndexUpdate {
private final Map allClasses = new HashMap();
/**
- * Creates a new empty index for a HTML report.
+ * Creates a new empty index for an HTML report.
*
* @param baseFolder
* base folder where all links are calculated relative to
From e4d600ab24ae2f3dea8231f15e13d71876e77bda Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 14:36:17 +0100
Subject: [PATCH 110/163] Fix typo: replace "a agent" by "an agent" (#1795)
"an" should be used instead of "a" when the
following word starts with a vowel sound.
---
org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java | 2 +-
org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
index 4d5d82179c..0568acb1b2 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
@@ -64,7 +64,7 @@ public void run() {
}
/**
- * Returns a global instance which is already started. If a agent has not
+ * Returns a global instance which is already started. If an agent has not
* been initialized before this method will fail.
*
* @return global instance
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
index d3b29d3c9d..e9e862db98 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
@@ -610,7 +610,7 @@ public String getQuotedVMArgument(final File agentJarFile) {
/**
* Generate required quotes JVM argument based on current configuration and
- * prepends it to the given argument command line. If a agent with the same
+ * prepends it to the given argument command line. If an agent with the same
* JAR file is already specified this parameter is removed from the existing
* command line.
*
From 081d054a06e944625546d50a463fc72e1bba67d1 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 21:13:45 +0100
Subject: [PATCH 111/163] Add unit test for ClassFieldProbeArrayStrategy
(#1796)
---
.../ClassFieldProbeArrayStrategyTest.java | 113 ++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategyTest.java
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategyTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategyTest.java
new file mode 100644
index 0000000000..d96eccc05f
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategyTest.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.instr;
+
+import static org.junit.Assert.assertEquals;
+
+import org.jacoco.core.instr.MethodRecorder;
+import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit test for {@link ClassFieldProbeArrayStrategy}.
+ */
+public class ClassFieldProbeArrayStrategyTest {
+
+ private ClassFieldProbeArrayStrategy create(final boolean withFrames) {
+ return new ClassFieldProbeArrayStrategy("ClassName", 1L, withFrames,
+ new IExecutionDataAccessorGenerator() {
+ public int generateDataAccessor(final long classid,
+ final String classname, final int probecount,
+ final MethodVisitor mv) {
+ assertEquals(1L, classid);
+ assertEquals("ClassName", classname);
+ assertEquals(2, probecount);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "Runtime",
+ "getProbes", "()[Z", false);
+ return 0;
+ }
+ });
+ }
+
+ @Test
+ public void should_add_field_and_init_method() {
+ for (final boolean withFrames : new boolean[] { true, false }) {
+ final ClassFieldProbeArrayStrategy strategy = create(withFrames);
+
+ final ClassNode c = new ClassNode();
+ strategy.addMembers(c, 2);
+
+ assertEquals(1, c.fields.size());
+ final FieldNode f = c.fields.get(0);
+ assertEquals(
+ Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT,
+ f.access);
+ assertEquals("$jacocoData", f.name);
+ assertEquals("[Z", f.desc);
+
+ assertEquals(1, c.methods.size());
+ final MethodNode m = c.methods.get(0);
+ assertEquals(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_STATIC, m.access);
+ assertEquals("$jacocoInit", m.name);
+ assertEquals("()[Z", m.desc);
+ final MethodRecorder expectedMethod = new MethodRecorder();
+ final MethodVisitor expected = expectedMethod.getVisitor();
+ expected.visitFieldInsn(Opcodes.GETSTATIC, "ClassName",
+ "$jacocoData", "[Z");
+ expected.visitInsn(Opcodes.DUP);
+ final Label label = new Label();
+ expected.visitJumpInsn(Opcodes.IFNONNULL, label);
+ expected.visitInsn(Opcodes.POP);
+ expected.visitMethodInsn(Opcodes.INVOKESTATIC, "Runtime",
+ "getProbes", "()[Z", false);
+ expected.visitInsn(Opcodes.DUP);
+ expected.visitFieldInsn(Opcodes.PUTSTATIC, "ClassName",
+ "$jacocoData", "[Z");
+ if (withFrames) {
+ expected.visitFrame(Opcodes.F_FULL, 0, new Object[] {}, 1,
+ new Object[] { "[Z" });
+ }
+ expected.visitLabel(label);
+ expected.visitInsn(Opcodes.ARETURN);
+ final MethodRecorder actualMethod = new MethodRecorder();
+ m.instructions.accept(actualMethod.getVisitor());
+ assertEquals(expectedMethod, actualMethod);
+ }
+ }
+
+ @Test
+ public void should_store_instance() {
+ final ClassFieldProbeArrayStrategy strategy = create(true);
+
+ final MethodRecorder actualMethod = new MethodRecorder();
+ final int maxStack = strategy.storeInstance(actualMethod.getVisitor(),
+ false, 13);
+ assertEquals(1, maxStack);
+
+ final MethodRecorder expectedMethod = new MethodRecorder();
+ final MethodVisitor expected = expectedMethod.getVisitor();
+ expected.visitMethodInsn(Opcodes.INVOKESTATIC, "ClassName",
+ "$jacocoInit", "()[Z", false);
+ expected.visitVarInsn(Opcodes.ASTORE, 13);
+ assertEquals(expectedMethod, actualMethod);
+ }
+
+}
From b71736944cf29cfc0a51292a3f6885ea3a377cd4 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 25 Nov 2024 23:56:20 +0100
Subject: [PATCH 112/163] Fix javadoc doclint warnings "no comment" (#1798)
---
.../src/org/jacoco/core/analysis/CounterComparator.java | 7 +++++++
.../src/org/jacoco/core/analysis/NodeComparator.java | 6 ++++++
.../core/data/IncompatibleExecDataVersionException.java | 3 +++
.../jacoco/core/internal/analysis/ClassCoverageImpl.java | 7 +++++++
.../internal/analysis/filter/KotlinGeneratedFilter.java | 9 +++++++++
.../jacoco/core/internal/analysis/filter/KotlinSMAP.java | 4 ++++
6 files changed, 36 insertions(+)
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java b/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
index 2845a6a381..fcf143e739 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
@@ -56,7 +56,14 @@ public class CounterComparator implements Comparator, Serializable {
public static final CounterComparator MISSEDRATIO = new CounterComparator(
CounterValue.MISSEDRATIO);
+ /**
+ * Counter value to sort on.
+ */
private final CounterValue value;
+
+ /**
+ * Specifies whether values are sorted in reverse order or not.
+ */
private final boolean reverse;
private CounterComparator(final CounterValue value) {
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java b/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
index e5ad65bf72..1bbbbff9ca 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
@@ -31,8 +31,14 @@ public class NodeComparator implements Comparator, Serializable {
private static final long serialVersionUID = 8550521643608826519L;
+ /**
+ * Comparator to compare {@link ICounter} objects.
+ */
private final Comparator counterComparator;
+ /**
+ * Counter entity to sort on.
+ */
private final CounterEntity entity;
NodeComparator(final Comparator counterComparator,
diff --git a/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java b/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
index 7cb998043b..32d93c4840 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
@@ -21,6 +21,9 @@ public class IncompatibleExecDataVersionException extends IOException {
private static final long serialVersionUID = 1L;
+ /**
+ * Actual version found in the execution data.
+ */
private final int actualVersion;
/**
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
index f4dc7e8870..b315d25703 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
@@ -119,6 +119,13 @@ public Collection getFragments() {
return fragments;
}
+ /**
+ * Stores fragments that contain coverage information about other nodes
+ * collected during the creation of this node.
+ *
+ * @param fragments
+ * fragments to store
+ */
public void setFragments(final Collection fragments) {
this.fragments = fragments;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
index 2bc32b1a21..535bd6a082 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
@@ -24,6 +24,15 @@ public class KotlinGeneratedFilter implements IFilter {
static final String KOTLIN_METADATA_DESC = "Lkotlin/Metadata;";
+ /**
+ * Checks whether the class corresponding to the given context has
+ * kotlin/Metadata annotation.
+ *
+ * @param context
+ * context information
+ * @return true if the class corresponding to the given context
+ * has kotlin/Metadata annotation
+ */
public static boolean isKotlinClass(final IFilterContext context) {
return context.getClassAnnotations().contains(KOTLIN_METADATA_DESC);
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java
index aa7a8d7b12..a3de7d9a77 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java
@@ -26,6 +26,10 @@
*/
public final class KotlinSMAP {
+ /**
+ * Parsed representation of a single LineSection from SourceDebugExtension
+ * attribute.
+ */
public static final class Mapping {
private final String inputClassName;
private final int inputStartLine;
From 83dba7880aef2ebffcec91012a3544cab6877ad8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 27 Nov 2024 15:38:01 +0000
Subject: [PATCH 113/163] Upgrade Kotlin to 2.1.0 (#1802)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evgeny Mandrikov
---
org.jacoco.core.test.validation.kotlin/pom.xml | 2 +-
org.jacoco.core.test.validation/pom.xml | 7 +++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml
index 24e23fa3c9..3708dc868d 100644
--- a/org.jacoco.core.test.validation.kotlin/pom.xml
+++ b/org.jacoco.core.test.validation.kotlin/pom.xml
@@ -25,7 +25,7 @@
JaCoCo :: Test :: Core :: Validation Kotlin
- 2.0.21
+ 2.1.0
diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml
index b18a0e1690..2d6edc5f12 100644
--- a/org.jacoco.core.test.validation/pom.xml
+++ b/org.jacoco.core.test.validation/pom.xml
@@ -504,8 +504,7 @@
-
- 22
+ 2316
@@ -533,8 +532,8 @@
-
- 22
+
+ 2316
From 46f0a6dfe349a3a220187735bcf0e3dd27018a28 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Thu, 28 Nov 2024 00:24:19 +0100
Subject: [PATCH 114/163] Upgrade maven-invoker-plugin to 3.8.1 (#1457)
---
.github/dependabot.yml | 1 -
jacoco-maven-plugin.test/pom.xml | 12 +++++++++---
org.jacoco.build/pom.xml | 2 +-
org.jacoco.examples.test/pom.xml | 6 ++++++
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d5d2b4272d..0a6c79fce2 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -22,7 +22,6 @@ updates:
ignore:
# It is known that upgrade from current version requires additional changes:
- dependency-name: "org.apache.maven.plugins:maven-plugin-plugin"
- - dependency-name: "org.apache.maven.plugins:maven-invoker-plugin"
# Because of
# https://github.com/apache/maven-compiler-plugin/blob/maven-compiler-plugin-3.13.0/pom.xml#L71
# https://github.com/codehaus-plexus/plexus-compiler/blob/plexus-compiler-2.15.0/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java#L149-L163
diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml
index ffca23e99c..81e8e2468e 100644
--- a/jacoco-maven-plugin.test/pom.xml
+++ b/jacoco-maven-plugin.test/pom.xml
@@ -32,6 +32,15 @@
org.jacoco.maven.*
+
+
+ ${project.groupId}
+ jacoco-maven-plugin
+ ${project.version}
+ maven-plugin
+
+
+
@@ -52,9 +61,6 @@
installit/settings.xml
-
- org.jacoco:org.jacoco.agent:${project.version}:jar:runtime
- ecj
diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml
index 2d6edc5f12..10583e0524 100644
--- a/org.jacoco.core.test.validation/pom.xml
+++ b/org.jacoco.core.test.validation/pom.xml
@@ -554,6 +554,39 @@
+
+ java25-bytecode
+
+
+ bytecode.version
+ 25
+
+
+
+
+ 23
+
+ 16
+
+ 25
+ 25
+
+
+
+ ../org.jacoco.core.test.validation.java7
+ ../org.jacoco.core.test.validation.java8
+ ../org.jacoco.core.test.validation.java14
+ ../org.jacoco.core.test.validation.java16
+ ../org.jacoco.core.test.validation.java21
+
+ ../org.jacoco.core.test.validation.scala
+
+
+
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
index b4ac0c865b..69d7af7763 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
@@ -132,13 +132,13 @@ private static byte[] createClass(final int version) {
*/
@Test
public void analyzeClass_should_throw_exception_for_unsupported_class_file_version() {
- final byte[] bytes = createClass(Opcodes.V23 + 2);
+ final byte[] bytes = createClass(Opcodes.V24 + 2);
try {
analyzer.analyzeClass(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
- assertEquals("Unsupported class file major version 69",
+ assertEquals("Unsupported class file major version 70",
e.getCause().getMessage());
}
}
@@ -218,14 +218,14 @@ public void testAnalyzeClass_BrokenStream() throws IOException {
*/
@Test
public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() {
- final byte[] bytes = createClass(Opcodes.V23 + 2);
+ final byte[] bytes = createClass(Opcodes.V24 + 2);
try {
analyzer.analyzeAll(new ByteArrayInputStream(bytes),
"UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
- assertEquals("Unsupported class file major version 69",
+ assertEquals("Unsupported class file major version 70",
e.getCause().getMessage());
}
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java
index e3b31b2d9d..2d8172a779 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java
@@ -31,6 +31,9 @@
import static org.objectweb.asm.Opcodes.V14;
import static org.objectweb.asm.Opcodes.V15;
import static org.objectweb.asm.Opcodes.V16;
+import static org.objectweb.asm.Opcodes.V17;
+import static org.objectweb.asm.Opcodes.V18;
+import static org.objectweb.asm.Opcodes.V19;
import static org.objectweb.asm.Opcodes.V1_1;
import static org.objectweb.asm.Opcodes.V1_2;
import static org.objectweb.asm.Opcodes.V1_3;
@@ -39,6 +42,11 @@
import static org.objectweb.asm.Opcodes.V1_6;
import static org.objectweb.asm.Opcodes.V1_7;
import static org.objectweb.asm.Opcodes.V1_8;
+import static org.objectweb.asm.Opcodes.V20;
+import static org.objectweb.asm.Opcodes.V21;
+import static org.objectweb.asm.Opcodes.V22;
+import static org.objectweb.asm.Opcodes.V23;
+import static org.objectweb.asm.Opcodes.V24;
import static org.objectweb.asm.Opcodes.V9;
import java.io.IOException;
@@ -139,6 +147,51 @@ public void test_16() throws IOException {
testVersion(V16, true);
}
+ @Test
+ public void test_17() throws IOException {
+ testVersion(V17, true);
+ }
+
+ @Test
+ public void test_18() throws IOException {
+ testVersion(V18, true);
+ }
+
+ @Test
+ public void test_19() throws IOException {
+ testVersion(V19, true);
+ }
+
+ @Test
+ public void test_20() throws IOException {
+ testVersion(V20, true);
+ }
+
+ @Test
+ public void test_21() throws IOException {
+ testVersion(V21, true);
+ }
+
+ @Test
+ public void test_22() throws IOException {
+ testVersion(V22, true);
+ }
+
+ @Test
+ public void test_23() throws IOException {
+ testVersion(V23, true);
+ }
+
+ @Test
+ public void test_24() throws IOException {
+ testVersion(V24, true);
+ }
+
+ @Test
+ public void test_25() throws IOException {
+ testVersion(V24 + 1, true);
+ }
+
private void testVersion(int version, boolean frames) throws IOException {
final byte[] original = createClass(version, frames);
diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
index 04a0ba972f..2c9d596e70 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
@@ -123,13 +123,13 @@ private static byte[] createClass(final int version) {
*/
@Test
public void instrument_should_throw_exception_for_unsupported_class_file_version() {
- final byte[] bytes = createClass(Opcodes.V23 + 2);
+ final byte[] bytes = createClass(Opcodes.V24 + 2);
try {
instrumenter.instrument(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
- assertEquals("Unsupported class file major version 69",
+ assertEquals("Unsupported class file major version 70",
e.getCause().getMessage());
}
}
@@ -221,14 +221,14 @@ public void testSerialization() throws Exception {
*/
@Test
public void instrumentAll_should_throw_exception_for_unsupported_class_file_version() {
- final byte[] bytes = createClass(Opcodes.V23 + 2);
+ final byte[] bytes = createClass(Opcodes.V24 + 2);
try {
instrumenter.instrumentAll(new ByteArrayInputStream(bytes),
new ByteArrayOutputStream(), "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
- assertEquals("Unsupported class file major version 69",
+ assertEquals("Unsupported class file major version 70",
e.getCause().getMessage());
}
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
index 1ee2e7d74a..fa96a54caf 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
@@ -43,8 +43,8 @@ public void setup() {
}
@Test
- public void classReaderFor_should_read_java_24_class() {
- final byte[] bytes = createJava24Class();
+ public void classReaderFor_should_read_java_25_class() {
+ final byte[] bytes = createJava25Class();
final ClassReader classReader = InstrSupport.classReaderFor(bytes);
@@ -53,16 +53,16 @@ public void classReaderFor_should_read_java_24_class() {
public void visit(final int version, final int access,
final String name, final String signature,
final String superName, final String[] interfaces) {
- assertEquals(Opcodes.V23 + 1, version);
+ assertEquals(Opcodes.V24 + 1, version);
}
}, 0);
- assertArrayEquals(createJava24Class(), bytes);
+ assertArrayEquals(createJava25Class(), bytes);
}
- private static byte[] createJava24Class() {
+ private static byte[] createJava25Class() {
final ClassWriter cw = new ClassWriter(0);
- cw.visit(Opcodes.V23 + 1, 0, "Foo", null, "java/lang/Object", null);
+ cw.visit(Opcodes.V24 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visitEnd();
return cw.toByteArray();
}
@@ -135,7 +135,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_
assertTrue(InstrSupport.needsFrames(Opcodes.V21));
assertTrue(InstrSupport.needsFrames(Opcodes.V22));
assertTrue(InstrSupport.needsFrames(Opcodes.V23));
- assertTrue(InstrSupport.needsFrames(Opcodes.V23 + 1));
+ assertTrue(InstrSupport.needsFrames(Opcodes.V24));
+ assertTrue(InstrSupport.needsFrames(Opcodes.V24 + 1));
assertTrue(InstrSupport.needsFrames(0x0100));
}
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 e3417a3d7a..bd54e2d680 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
@@ -32,6 +32,7 @@
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.core.internal.instr.InstrSupport;
import org.jacoco.core.test.InstrumentingLoader;
import org.jacoco.core.test.TargetLoader;
import org.jacoco.core.test.validation.Source.Line;
@@ -44,7 +45,6 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runners.model.MultipleFailureException;
-import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;
@@ -124,9 +124,10 @@ private void saveBytecodeRepresentations(final byte[] classBytes,
new File(outputDir, fileName + ".txt"));
final PrintWriter asmWriter = new PrintWriter(
new File(outputDir, fileName + ".java"));
- new ClassReader(classBytes).accept(new TraceClassVisitor(
- new TraceClassVisitor(null, new Textifier(), textWriter),
- new ASMifier(), asmWriter), 0);
+ InstrSupport.classReaderFor(classBytes)
+ .accept(new TraceClassVisitor(new TraceClassVisitor(null,
+ new Textifier(), textWriter), new ASMifier(),
+ asmWriter), 0);
textWriter.close();
asmWriter.close();
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
index c52810e663..dc4df54e01 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
@@ -273,9 +273,9 @@ public static void push(final MethodVisitor mv, final int value) {
*/
public static ClassReader classReaderFor(final byte[] b) {
final int originalVersion = getMajorVersion(b);
- if (originalVersion == Opcodes.V23 + 1) {
+ if (originalVersion == Opcodes.V24 + 1) {
// temporarily downgrade version to bypass check in ASM
- setMajorVersion(Opcodes.V23, b);
+ setMajorVersion(Opcodes.V24, b);
}
final ClassReader classReader = new ClassReader(b);
setMajorVersion(originalVersion, b);
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 2a5caaa836..c4ce95b553 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -34,6 +34,8 @@
Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?
What Java versions are supported by JaCoCo?
- JaCoCo supports Java class files from version 1.0 to 23. However the minimum
- JRE version required by the JaCoCo runtime (e.g. the agent) and the JaCoCo
- tools is 1.5. Also note that class files under test from version 1.6 and above
- have to contain valid stackmap frames.
+ JaCoCo officially supports Java class files from version 1.0 to 23. Also
+ experimental support for class files of versions 24 and 25 is provided.
+ However the minimum JRE version required by the JaCoCo runtime
+ (e.g. the agent) and the JaCoCo tools is 1.5. Also note that class files under
+ test from version 1.6 and above have to contain valid stackmap frames.
Why do I get the error "Can't add different class with same name"?
From 5a6a5c4719aa009c1f2117f4ccc04d19d6d812fc Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 9 Dec 2024 15:19:20 +0100
Subject: [PATCH 120/163] IFilter implementations should be package-private and
final (#1806)
---
.../core/internal/analysis/ClassAnalyzer.java | 4 +---
.../filter/AnnotationGeneratedFilter.java | 2 +-
.../filter/EnumEmptyConstructorFilter.java | 2 +-
.../internal/analysis/filter/EnumFilter.java | 2 +-
.../core/internal/analysis/filter/Filters.java | 14 ++++++++++++++
.../internal/analysis/filter/FinallyFilter.java | 2 +-
.../analysis/filter/KotlinComposeFilter.java | 2 +-
.../analysis/filter/KotlinCoroutineFilter.java | 4 ++--
.../filter/KotlinDefaultArgumentsFilter.java | 4 ++--
.../filter/KotlinDefaultMethodsFilter.java | 2 +-
.../analysis/filter/KotlinEnumFilter.java | 2 +-
.../analysis/filter/KotlinGeneratedFilter.java | 17 ++---------------
.../filter/KotlinInlineClassFilter.java | 2 +-
.../analysis/filter/KotlinInlineFilter.java | 4 ++--
.../analysis/filter/KotlinLateinitFilter.java | 2 +-
.../filter/KotlinNotNullOperatorFilter.java | 2 +-
.../filter/KotlinUnsafeCastOperatorFilter.java | 4 ++--
.../analysis/filter/KotlinWhenFilter.java | 2 +-
.../analysis/filter/KotlinWhenStringFilter.java | 2 +-
.../PrivateEmptyNoArgConstructorFilter.java | 2 +-
.../internal/analysis/filter/RecordsFilter.java | 2 +-
.../analysis/filter/StringSwitchFilter.java | 2 +-
.../filter/StringSwitchJavacFilter.java | 2 +-
.../analysis/filter/SynchronizedFilter.java | 2 +-
.../analysis/filter/SyntheticFilter.java | 4 ++--
.../filter/TryWithResourcesEcjFilter.java | 2 +-
.../filter/TryWithResourcesJavac11Filter.java | 2 +-
.../filter/TryWithResourcesJavacFilter.java | 2 +-
28 files changed, 47 insertions(+), 48 deletions(-)
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 d2268c5507..fa49d5385a 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
@@ -21,7 +21,6 @@
import org.jacoco.core.internal.analysis.filter.Filters;
import org.jacoco.core.internal.analysis.filter.IFilter;
import org.jacoco.core.internal.analysis.filter.IFilterContext;
-import org.jacoco.core.internal.analysis.filter.KotlinGeneratedFilter;
import org.jacoco.core.internal.analysis.filter.KotlinSMAP;
import org.jacoco.core.internal.flow.ClassProbesVisitor;
import org.jacoco.core.internal.flow.MethodProbesVisitor;
@@ -144,8 +143,7 @@ private void addMethodCoverage(final String name, final String desc,
private void calculateFragments(
final Map instructions) {
- if (sourceDebugExtension == null
- || !KotlinGeneratedFilter.isKotlinClass(this)) {
+ if (sourceDebugExtension == null || !Filters.isKotlinClass(this)) {
return;
}
if (smap == null) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java
index cd7818d85c..9e80e75b98 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java
@@ -23,7 +23,7 @@
* {@link java.lang.annotation.RetentionPolicy#CLASS invisible} annotation whose
* simple name contains Generated.
*/
-public final class AnnotationGeneratedFilter implements IFilter {
+final class AnnotationGeneratedFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java
index bfc2d80988..e63e17c263 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java
@@ -29,7 +29,7 @@
* constructors} - empty constructor in enums without additional parameters
* should be filtered out even if it is not implicit.
*/
-public final class EnumEmptyConstructorFilter implements IFilter {
+final class EnumEmptyConstructorFilter implements IFilter {
private static final String CONSTRUCTOR_NAME = "";
private static final String CONSTRUCTOR_DESC = "(Ljava/lang/String;I)V";
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
index 22bc1f0100..7ea7b99fcd 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
@@ -18,7 +18,7 @@
* Filters methods values and valueOf that compiler
* creates for enums.
*/
-public final class EnumFilter implements IFilter {
+final class EnumFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
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 de1a1f3612..11b748caf5 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
@@ -65,4 +65,18 @@ public void filter(final MethodNode methodNode,
}
}
+ /**
+ * Checks whether the class corresponding to the given context has
+ * kotlin/Metadata annotation.
+ *
+ * @param context
+ * context information
+ * @return true if the class corresponding to the given context
+ * has kotlin/Metadata annotation
+ */
+ public static boolean isKotlinClass(final IFilterContext context) {
+ return context.getClassAnnotations()
+ .contains(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+ }
+
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
index a421fc24b0..bc06d1d600 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
@@ -66,7 +66,7 @@
* at once, because execution can branch from one region to another (like it is
* in given example due to "if" statement).
*/
-public final class FinallyFilter implements IFilter {
+final class FinallyFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.java
index 48a1fbd565..62a53d9235 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.java
@@ -26,7 +26,7 @@ final class KotlinComposeFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
if (!isComposable(methodNode)) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
index 64a2016175..c83c28b8cc 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
@@ -26,12 +26,12 @@
/**
* Filters branches that Kotlin compiler generates for coroutines.
*/
-public final class KotlinCoroutineFilter implements IFilter {
+final class KotlinCoroutineFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
index 978dd29750..61643f138d 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
@@ -50,7 +50,7 @@
*
* This filter marks IFEQ instructions as ignored.
*/
-public final class KotlinDefaultArgumentsFilter implements IFilter {
+final class KotlinDefaultArgumentsFilter implements IFilter {
private static boolean isDefaultArgumentsMethod(
final MethodNode methodNode) {
@@ -76,7 +76,7 @@ public void filter(final MethodNode methodNode,
if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) {
return;
}
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilter.java
index 4ae6b1e93e..d79952216b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilter.java
@@ -24,7 +24,7 @@ final class KotlinDefaultMethodsFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
new Matcher().match(methodNode, output);
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.java
index 5d9891d3f9..43737cd6f0 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.java
@@ -25,7 +25,7 @@ public void filter(final MethodNode methodNode,
if (!"java/lang/Enum".equals(context.getSuperClassName())) {
return;
}
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
if (!"getEntries".equals(methodNode.name)) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
index 535bd6a082..7e7b67e0b6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
@@ -20,23 +20,10 @@
* identified by the @kotlin.Metadata annotations. In such classes
* generated methods do not have line numbers.
*/
-public class KotlinGeneratedFilter implements IFilter {
+final class KotlinGeneratedFilter implements IFilter {
static final String KOTLIN_METADATA_DESC = "Lkotlin/Metadata;";
- /**
- * Checks whether the class corresponding to the given context has
- * kotlin/Metadata annotation.
- *
- * @param context
- * context information
- * @return true if the class corresponding to the given context
- * has kotlin/Metadata annotation
- */
- public static boolean isKotlinClass(final IFilterContext context) {
- return context.getClassAnnotations().contains(KOTLIN_METADATA_DESC);
- }
-
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
@@ -46,7 +33,7 @@ public void filter(final MethodNode methodNode,
return;
}
- if (!isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java
index 0279e04786..41ad6d4e19 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java
@@ -73,7 +73,7 @@ final class KotlinInlineClassFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
if (!context.getClassAnnotations().contains("Lkotlin/jvm/JvmInline;")) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
index 55c2d77fbf..1a3bbe9e7c 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
@@ -19,7 +19,7 @@
/**
* Filters out instructions that were inlined by Kotlin compiler.
*/
-public final class KotlinInlineFilter implements IFilter {
+final class KotlinInlineFilter implements IFilter {
private int firstGeneratedLineNumber = -1;
@@ -29,7 +29,7 @@ public void filter(final MethodNode methodNode,
return;
}
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
index 0dd736c57e..a098f48d17 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
@@ -22,7 +22,7 @@
* Filters branch in bytecode that Kotlin compiler generates for reading from
* lateinit properties.
*/
-public class KotlinLateinitFilter implements IFilter {
+final class KotlinLateinitFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java
index e6a2964284..d8d377224a 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java
@@ -20,7 +20,7 @@
* Filters branch in bytecode that Kotlin compiler generates for not-null
* assertion operator.
*/
-public final class KotlinNotNullOperatorFilter implements IFilter {
+final class KotlinNotNullOperatorFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java
index fd03de534e..559bda4b21 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java
@@ -22,11 +22,11 @@
* Filters branch in bytecode that Kotlin compiler generates for "unsafe" cast
* operator.
*/
-public final class KotlinUnsafeCastOperatorFilter implements IFilter {
+final class KotlinUnsafeCastOperatorFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
- if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (!Filters.isKotlinClass(context)) {
return;
}
final Matcher matcher = new Matcher();
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
index 202ed3bea6..dcd5e810f4 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
@@ -30,7 +30,7 @@
* expressions and statements with subject of type enum class or
* sealed class.
*/
-public final class KotlinWhenFilter implements IFilter {
+final class KotlinWhenFilter implements IFilter {
private static final String EXCEPTION = "kotlin/NoWhenBranchMatchedException";
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java
index 5f34035dab..9946178dcd 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java
@@ -28,7 +28,7 @@
* Filters bytecode that Kotlin compiler generates for when
* expressions with a String.
*/
-public final class KotlinWhenStringFilter implements IFilter {
+final class KotlinWhenStringFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
index c2a4e64322..084814bf53 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
@@ -18,7 +18,7 @@
/**
* Filters private empty constructors that do not have arguments.
*/
-public final class PrivateEmptyNoArgConstructorFilter implements IFilter {
+final class PrivateEmptyNoArgConstructorFilter implements IFilter {
private static final String CONSTRUCTOR_NAME = "";
private static final String CONSTRUCTOR_DESC = "()V";
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/RecordsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/RecordsFilter.java
index f7ab5c7f5d..8bedef2d09 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/RecordsFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/RecordsFilter.java
@@ -22,7 +22,7 @@
* Filters methods toString, hashCode and
* equals that compiler generates for records.
*/
-public final class RecordsFilter implements IFilter {
+final class RecordsFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
index 16861854bb..10cf5917e2 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
@@ -29,7 +29,7 @@
* with a String and by Kotlin compiler 1.5 and above for a
* when expression with a String.
*/
-public final class StringSwitchFilter implements IFilter {
+final class StringSwitchFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
index cf48d00603..2dab00fad9 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
@@ -23,7 +23,7 @@
/**
* Filters code that is generated by javac for a switch statement with a String.
*/
-public final class StringSwitchJavacFilter implements IFilter {
+final class StringSwitchJavacFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
index 0e212a4890..35d7cff883 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
@@ -20,7 +20,7 @@
/**
* Filters code that is generated for synchronized statement.
*/
-public final class SynchronizedFilter implements IFilter {
+final class SynchronizedFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
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
index 55e35a621c..f260d01cf2 100644
--- 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
@@ -18,7 +18,7 @@
/**
* Filters synthetic methods unless they represent bodies of lambda expressions.
*/
-public final class SyntheticFilter implements IFilter {
+final class SyntheticFilter implements IFilter {
private static boolean isScalaClass(final IFilterContext context) {
return context.getClassAttributes().contains("ScalaSig")
@@ -41,7 +41,7 @@ public void filter(final MethodNode methodNode,
}
}
- if (KotlinGeneratedFilter.isKotlinClass(context)) {
+ if (Filters.isKotlinClass(context)) {
if (!methodNode.name.startsWith("access$")) {
return;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
index ec560a457d..c59398c4be 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
@@ -26,7 +26,7 @@
/**
* Filters code that ECJ generates for try-with-resources statement.
*/
-public final class TryWithResourcesEcjFilter implements IFilter {
+final class TryWithResourcesEcjFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java
index ddd24c2a3b..e381c85041 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java
@@ -22,7 +22,7 @@
* Filters code which is generated for try-with-resources statement by javac
* starting from version 11.
*/
-public final class TryWithResourcesJavac11Filter implements IFilter {
+final class TryWithResourcesJavac11Filter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
index e56a556980..261f4b0c3b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
@@ -22,7 +22,7 @@
* Filters code which is generated for try-with-resources statement by javac
* versions from 7 to 10.
*/
-public final class TryWithResourcesJavacFilter implements IFilter {
+final class TryWithResourcesJavacFilter implements IFilter {
public void filter(final MethodNode methodNode,
final IFilterContext context, final IFilterOutput output) {
From fac812ea0c5de6cc5721ce6f22f27d69525efcde Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 9 Dec 2024 19:49:08 +0100
Subject: [PATCH 121/163] Add validation test for `synchronized` block in
Kotlin (#1703)
---
.../kotlin/KotlinSynchronizedTest.java | 27 +++++++++
.../targets/KotlinSynchronizedTarget.kt | 57 +++++++++++++++++++
2 files changed, 84 insertions(+)
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSynchronizedTest.java
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSynchronizedTarget.kt
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSynchronizedTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSynchronizedTest.java
new file mode 100644
index 0000000000..9bb2904b68
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSynchronizedTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinSynchronizedTarget;
+
+/**
+ * Test of code coverage in {@link KotlinSynchronizedTarget}
+ */
+public class KotlinSynchronizedTest extends ValidationTestBase {
+
+ public KotlinSynchronizedTest() {
+ super(KotlinSynchronizedTarget.class);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSynchronizedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSynchronizedTarget.kt
new file mode 100644
index 0000000000..7c52b03fd1
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSynchronizedTarget.kt
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.*
+
+/**
+ * Test target with [synchronized] block.
+ */
+object KotlinSynchronizedTarget {
+
+ private val lock = Any();
+
+ private fun normal() {
+ synchronized(lock) { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ } // assertFullyCovered()
+ }
+
+ private fun explicitException() {
+ synchronized(lock) { // assertFullyCovered()
+ throw StubException() // assertFullyCovered()
+ } // assertEmpty()
+ }
+
+ private fun implicitException() {
+ synchronized(lock) { // assertPartlyCovered()
+ ex() // assertNotCovered()
+ } // assertNotCovered()
+ }
+
+ @JvmStatic
+ fun main(args: Array) {
+ normal()
+
+ try {
+ explicitException()
+ } catch (_: StubException) {
+ }
+
+ try {
+ implicitException()
+ } catch (_: StubException) {
+ }
+ }
+
+}
From e8f0907904649b98fb901b3834f9025813223570 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Mon, 9 Dec 2024 21:11:43 +0100
Subject: [PATCH 122/163] Add validation test for exception based control flow
in Kotlin (#1671)
---
.../kotlin/KotlinExceptionsTest.java | 27 ++++
.../kotlin/targets/KotlinExceptionsTarget.kt | 133 ++++++++++++++++++
2 files changed, 160 insertions(+)
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinExceptionsTest.java
create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinExceptionsTarget.kt
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinExceptionsTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinExceptionsTest.java
new file mode 100644
index 0000000000..98cc5211c8
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinExceptionsTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinExceptionsTarget;
+
+/**
+ * Test of code coverage in {@link KotlinExceptionsTarget}.
+ */
+public class KotlinExceptionsTest extends ValidationTestBase {
+
+ public KotlinExceptionsTest() {
+ super(KotlinExceptionsTarget.class);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinExceptionsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinExceptionsTarget.kt
new file mode 100644
index 0000000000..2b2438c884
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinExceptionsTarget.kt
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.*
+
+/**
+ * Test target with exception based control flow examples.
+ */
+object KotlinExceptionsTarget {
+
+ private fun implicitArrayIndexOutOfBoundsException(a: Array) {
+ nop() // assertNotCovered()
+ a[0] // assertNotCovered()
+ nop() // assertNotCovered()
+ }
+
+ private fun implicitException() {
+ nop() // assertFullyCovered()
+ ex() // assertNotCovered()
+ nop() // assertNotCovered()
+ }
+
+ private fun explicitException() {
+ nop() // assertFullyCovered()
+ throw StubException() // assertFullyCovered()
+ }
+
+ private fun noExceptionTryCatch() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ } catch (e: StubException) { // assertNotCovered()
+ nop() // assertNotCovered()
+ } // assertEmpty()
+ }
+
+ private fun implicitExceptionTryCatch() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ ex() // assertNotCovered()
+ nop() // assertNotCovered()
+ } catch (e: StubException) { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ } // assertEmpty()
+ }
+
+ private fun explicitExceptionTryCatch() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ throw StubException() // assertFullyCovered()
+ } catch (e: StubException) { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ } // assertEmpty()
+ }
+
+ private fun noExceptionFinally() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ } finally { // assertEmpty()
+ nop() // assertFullyCovered()
+ } // assertEmpty()
+ }
+
+ private fun implicitExceptionFinally() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ ex() // assertNotCovered()
+ nop() // assertNotCovered()
+ } finally { // assertEmpty()
+ nop() // assertFullyCovered()
+ } // assertEmpty()
+ }
+
+ private fun explicitExceptionFinally() {
+ nop() // assertFullyCovered()
+ try { // assertFullyCovered()
+ nop() // assertFullyCovered()
+ throw StubException() // assertFullyCovered()
+ } finally { // assertEmpty()
+ nop() // assertFullyCovered()
+ }
+ }
+
+ @JvmStatic
+ fun main(args: Array) {
+ try {
+ implicitArrayIndexOutOfBoundsException(arrayOf())
+ } catch (_: ArrayIndexOutOfBoundsException) {
+ }
+ try {
+ implicitException()
+ } catch (_: StubException) {
+ }
+ try {
+ explicitException()
+ } catch (_: StubException) {
+ }
+ noExceptionTryCatch()
+ try {
+ implicitExceptionTryCatch()
+ } catch (_: StubException) {
+ }
+ try {
+ explicitExceptionTryCatch()
+ } catch (_: StubException) {
+ }
+ noExceptionFinally()
+ try {
+ implicitExceptionFinally()
+ } catch (_: StubException) {
+ }
+ try {
+ explicitExceptionFinally()
+ } catch (_: StubException) {
+ }
+ }
+
+}
From e6f29c902242c24c20f7740e27006a83330b8e88 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 12 Dec 2024 15:13:49 +0100
Subject: [PATCH 123/163] Upgrade maven-javadoc-plugin to 3.11.2 (#1808)
Bump org.apache.maven.plugins:maven-javadoc-plugin in /org.jacoco.build
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.1 to 3.11.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.1...maven-javadoc-plugin-3.11.2)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
org.jacoco.build/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index ba52aa121a..e3fbc9a7f7 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -353,7 +353,7 @@
org.apache.maven.pluginsmaven-javadoc-plugin
- 3.11.1
+ 3.11.2truefalse
From aa0ebe8eb44d6ffe010afe134b6f0deb34491e81 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 13 Dec 2024 10:09:16 +0100
Subject: [PATCH 124/163] Add validation test for chain of elvis operators in
Kotlin (#1812)
---
.../kotlin/KotlinElvisOperatorTest.java | 2 +-
.../targets/KotlinElvisOperatorTarget.kt | 49 +++++++++++++++++--
2 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java
index b732d4453e..72c18440a9 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java
@@ -16,7 +16,7 @@
import org.jacoco.core.test.validation.kotlin.targets.KotlinElvisOperatorTarget;
/**
- * Test of elvis operator.
+ * Test of code coverage in {@link KotlinElvisOperatorTarget}.
*/
public class KotlinElvisOperatorTest extends ValidationTestBase {
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt
index 0310b6d072..c5d6b73315 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt
@@ -13,18 +13,57 @@
package org.jacoco.core.test.validation.kotlin.targets
/**
- * Test target for elvis operator.
+ * Test target for [elvis operator (`?:`)](https://kotlinlang.org/docs/null-safety.html#elvis-operator).
*/
object KotlinElvisOperatorTarget {
- private fun example(x: String?): String {
- return x ?: "" // assertFullyCovered(0, 2)
+ private fun elvis() {
+ fun nullOnly(a: String?): String =
+ a ?: "" // assertFullyCovered(1, 1)
+
+ fun nonNullOnly(a: String?): String =
+ a ?: "" // assertPartlyCovered(1, 1)
+
+ fun fullCoverage(a: String?): String =
+ a ?: "" // assertFullyCovered(0, 2)
+
+ nullOnly(null)
+ nonNullOnly("")
+ fullCoverage(null)
+ fullCoverage("")
+ }
+
+ private fun elvisChain() {
+ fun bothNull(a: String?, b: String?): String =
+ a ?: b ?: "" // assertFullyCovered(2, 2)
+
+ fun secondNonNull(a: String?, b: String?): String =
+ a ?: b ?: "" // assertPartlyCovered(2, 2)
+
+ fun firstNonNull(a: String?, b: String?): String =
+ a ?: b ?: "" // assertPartlyCovered(3, 1)
+
+ fun firstOrSecondNonNull(a: String?, b: String?): String =
+ a ?: b ?: "" // assertPartlyCovered(1, 3)
+
+ fun fullCoverage(a: String?, b: String?): String =
+ a ?: b ?: "" // assertFullyCovered(0, 4)
+
+ bothNull(null, null)
+ secondNonNull(null, "")
+ firstNonNull("", null)
+ firstNonNull("", "")
+ firstOrSecondNonNull("", null)
+ firstOrSecondNonNull(null, "")
+ fullCoverage(null, null)
+ fullCoverage("", null)
+ fullCoverage(null, "")
}
@JvmStatic
fun main(args: Array) {
- example("")
- example(null)
+ elvis()
+ elvisChain()
}
}
From 5d8e0855e3ce82cabf0042c668df41a1bce50095 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 13 Dec 2024 15:01:01 +0100
Subject: [PATCH 125/163] Upgrade sonar-maven-plugin to 5.0.0.4389 (#1771)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evgeny Mandrikov
---
.azure-pipelines/azure-pipelines.yml | 2 +-
org.jacoco.build/pom.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml
index 155504492b..7ed12a5f88 100644
--- a/.azure-pipelines/azure-pipelines.yml
+++ b/.azure-pipelines/azure-pipelines.yml
@@ -93,7 +93,7 @@ jobs:
elif [[ "$BUILD_SOURCEBRANCH" == "refs/heads/master" && "$JDK_VERSION" == "11" ]]; then
./mvnw -V -B -e --no-transfer-progress -f org.jacoco.build \
verify -Djdk.version=$JDK_VERSION -Dbytecode.version=$JDK_VERSION \
- sonar:sonar \
+ sonar:sonar -Dsonar.scanner.skipJreProvisioning \
--toolchains=toolchains.xml --settings=.azure-pipelines/maven-settings.xml
else
./mvnw -V -B -e --no-transfer-progress \
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index e3fbc9a7f7..4fa5493de5 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -455,7 +455,7 @@
org.sonarsource.scanner.mavensonar-maven-plugin
- 4.0.0.4121
+ 5.0.0.4389
From 6a1a43010d24eb79617b35795fd474d39a4f45a6 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Sun, 15 Dec 2024 23:43:45 +0100
Subject: [PATCH 126/163] Add filter for Kotlin safe call operators chains
(#1810)
---
.../kotlin/KotlinSafeCallOperatorTest.java | 2 +-
.../targets/KotlinSafeCallOperatorTarget.kt | 41 +++++++--
.../analysis/filter/FilterTestBase.java | 8 +-
.../KotlinSafeCallOperatorFilterTest.java | 83 +++++++++++++++++
.../internal/analysis/filter/Filters.java | 1 +
.../filter/KotlinSafeCallOperatorFilter.java | 90 +++++++++++++++++++
org.jacoco.doc/docroot/doc/changes.html | 3 +
7 files changed, 220 insertions(+), 8 deletions(-)
create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilterTest.java
create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilter.java
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java
index 203f62f3c9..ad5a25b31e 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java
@@ -16,7 +16,7 @@
import org.jacoco.core.test.validation.kotlin.targets.KotlinSafeCallOperatorTarget;
/**
- * Test of safe call operator.
+ * Test of code coverage in {@link KotlinSafeCallOperatorTarget}.
*/
public class KotlinSafeCallOperatorTest extends ValidationTestBase {
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt
index ec8dd708c9..96c94559fc 100644
--- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt
@@ -13,18 +13,49 @@
package org.jacoco.core.test.validation.kotlin.targets
/**
- * Test target for safe call operator.
+ * Test target for [safe call operator (`?.`)](https://kotlinlang.org/docs/null-safety.html#safe-call-operator).
*/
object KotlinSafeCallOperatorTarget {
- private fun example(x: String?): Int? {
- return x?.length // assertFullyCovered(0, 2)
+ data class A(val b: B)
+ data class B(val c: String)
+
+ private fun safeCall() {
+ fun nullOnly(b: B?): String? =
+ b?.c // assertPartlyCovered(1, 1)
+
+ fun nonNullOnly(b: B?): String? =
+ b?.c // assertPartlyCovered(1, 1)
+
+ fun fullCoverage(b: B?): String? =
+ b?.c // assertFullyCovered(0, 2)
+
+ nullOnly(null)
+ nonNullOnly(B(""))
+ fullCoverage(null)
+ fullCoverage(B(""))
+ }
+
+ private fun safeCallChain() {
+ fun nullOnly(a: A?): String? =
+ a?.b?.c // assertPartlyCovered(2, 2)
+
+ fun nonNullOnly(a: A?): String? =
+ a?.b?.c // assertPartlyCovered(2, 2)
+
+ fun fullCoverage(a: A?): String? =
+ a?.b?.c // assertFullyCovered(0, 4)
+
+ nullOnly(null)
+ nonNullOnly(A(B("")))
+ fullCoverage(null)
+ fullCoverage(A(B("")))
}
@JvmStatic
fun main(args: Array) {
- example("")
- example(null)
+ safeCall()
+ safeCallChain()
}
}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java
index 66162e5ad0..0e24547a11 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java
@@ -73,8 +73,12 @@ final void assertNoReplacedBranches() {
final void assertReplacedBranches(final AbstractInsnNode source,
final Set newTargets) {
- assertEquals(Collections.singletonMap(source, newTargets),
- replacedBranches);
+ assertReplacedBranches(Collections.singletonMap(source, newTargets));
+ }
+
+ final void assertReplacedBranches(
+ final Map> expected) {
+ assertEquals(expected, replacedBranches);
}
static class Range {
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilterTest.java
new file mode 100644
index 0000000000..9e0dc31290
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilterTest.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+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 KotlinSafeCallOperatorFilter}.
+ */
+public class KotlinSafeCallOperatorFilterTest extends FilterTestBase {
+
+ private final IFilter filter = new KotlinSafeCallOperatorFilter();
+
+ /**
+ *
+ * data class A(val b: B)
+ * data class B(val c: String)
+ * fun example(a: A?): String? =
+ * a?.b?.c
+ *
+ *
+ * https://github.com/JetBrains/kotlin/commit/0a67ab54fec635f82e0507cbdd4299ae0dbe71b0
+ */
+ @Test
+ public void should_filter_safe_call_chain() {
+ context.classAnnotations
+ .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "example", "(LA;)Ljava/lang/String;", null, null);
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ final Label label1 = new Label();
+ final Label label2 = new Label();
+
+ m.visitInsn(Opcodes.DUP);
+ m.visitJumpInsn(Opcodes.IFNULL, label1);
+ final AbstractInsnNode i1 = m.instructions.getLast();
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "A", "getB", "()LB;", false);
+
+ m.visitInsn(Opcodes.DUP);
+ m.visitJumpInsn(Opcodes.IFNULL, label1);
+ final AbstractInsnNode i2 = m.instructions.getLast();
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC",
+ "()Ljava/lang/String;", false);
+ final HashSet r = new HashSet();
+ r.add(m.instructions.getLast());
+
+ m.visitJumpInsn(Opcodes.GOTO, label2);
+
+ m.visitLabel(label1);
+ m.visitInsn(Opcodes.POP);
+ r.add(m.instructions.getLast());
+ m.visitInsn(Opcodes.ACONST_NULL);
+ m.visitLabel(label2);
+
+ filter.filter(m, context, output);
+
+ assertIgnored();
+ final HashMap> expected = new HashMap>();
+ expected.put(i1, r);
+ expected.put(i2, r);
+ assertReplacedBranches(expected);
+ }
+
+}
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 11b748caf5..1f7e600edd 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
@@ -44,6 +44,7 @@ public static IFilter all() {
new RecordPatternFilter(), //
new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(),
new KotlinEnumFilter(), //
+ new KotlinSafeCallOperatorFilter(), //
new KotlinLateinitFilter(), new KotlinWhenFilter(),
new KotlinWhenStringFilter(),
new KotlinUnsafeCastOperatorFilter(),
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilter.java
new file mode 100644
index 0000000000..887ff7ad87
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSafeCallOperatorFilter.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2024 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:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+
+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;
+
+/**
+ * Filters bytecode that Kotlin compiler generates for chains of safe call
+ * operators ({@code ?.}).
+ */
+final class KotlinSafeCallOperatorFilter implements IFilter {
+
+ public void filter(final MethodNode methodNode,
+ final IFilterContext context, final IFilterOutput output) {
+ if (!Filters.isKotlinClass(context)) {
+ return;
+ }
+ for (final ArrayList chain : findChains(methodNode)) {
+ if (chain.size() == 1) {
+ continue;
+ }
+ JumpInsnNode lastJump = chain.get(chain.size() - 1);
+ final HashSet newTargets = new HashSet();
+ newTargets.add(AbstractMatcher.skipNonOpcodes(lastJump.getNext()));
+ newTargets.add(AbstractMatcher.skipNonOpcodes(lastJump.label));
+ for (final AbstractInsnNode i : chain) {
+ output.replaceBranches(i, newTargets);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void should_filter_Kotlin_nullable_case() {
+ final Range range = new Range();
+ final Set expectedNewTargets = new HashSet();
+
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "example", "(Ljava/lang/String;)Ljava/lang/String;", null,
+ null);
+ final Label hashA = new Label();
+ final Label hashB = new Label();
+ final Label hashC = new Label();
+ final Label caseA = new Label();
+ final Label caseB = new Label();
+ final Label caseC = new Label();
+ final Label caseNull = new Label();
+ final Label caseElse = new Label();
+ final Label end = new Label();
+
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitVarInsn(Opcodes.ASTORE, 2);
+ m.visitVarInsn(Opcodes.ALOAD, 2);
+ range.fromInclusive = m.instructions.getLast();
+ m.visitInsn(Opcodes.DUP);
+ m.visitJumpInsn(Opcodes.IFNULL, caseNull);
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+ "()I", false);
+ m.visitTableSwitchInsn(97, 99, caseElse,
+ new Label[] { hashA, hashB, hashC });
+
+ m.visitLabel(hashA);
+ m.visitVarInsn(Opcodes.ALOAD, 2);
+ m.visitLdcInsn("a");
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+ "(Ljava/lang/Object;)Z", false);
+ m.visitJumpInsn(Opcodes.IFNE, caseA);
+ m.visitJumpInsn(Opcodes.GOTO, caseElse);
+
+ m.visitLabel(hashB);
+ m.visitVarInsn(Opcodes.ALOAD, 2);
+ m.visitLdcInsn("b");
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+ "(Ljava/lang/Object;)Z", false);
+ m.visitJumpInsn(Opcodes.IFNE, caseB);
+ m.visitJumpInsn(Opcodes.GOTO, caseElse);
+
+ m.visitLabel(hashC);
+ m.visitVarInsn(Opcodes.ALOAD, 2);
+ m.visitLdcInsn("c");
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+ "(Ljava/lang/Object;)Z", false);
+ m.visitJumpInsn(Opcodes.IFNE, caseC);
+ m.visitJumpInsn(Opcodes.GOTO, caseElse);
+ range.toInclusive = m.instructions.getLast();
+
+ m.visitLabel(caseA);
+ m.visitLdcInsn("case a");
+ expectedNewTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, end);
+
+ m.visitLabel(caseB);
+ m.visitLdcInsn("case b");
+ expectedNewTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, end);
+
+ m.visitLabel(caseC);
+ m.visitLdcInsn("case c");
+ expectedNewTargets.add(m.instructions.getLast());
+ m.visitJumpInsn(Opcodes.GOTO, end);
+
+ m.visitLabel(caseNull);
+ m.visitInsn(Opcodes.POP);
+ expectedNewTargets.add(m.instructions.getLast());
+ m.visitLdcInsn("null");
+ m.visitJumpInsn(Opcodes.GOTO, end);
+
+ m.visitLabel(caseElse);
+ m.visitLdcInsn("else");
+ expectedNewTargets.add(m.instructions.getLast());
+
+ m.visitLabel(end);
+ m.visitInsn(Opcodes.ARETURN);
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range);
+ assertReplacedBranches(range.fromInclusive.getPrevious(),
expectedNewTargets);
}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
index 10cf5917e2..21ab863e92 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilter.java
@@ -42,19 +42,35 @@ public void filter(final MethodNode methodNode,
private static class Matcher extends AbstractMatcher {
public void match(final AbstractInsnNode start,
final IFilterOutput output) {
-
- if (start.getOpcode() != /* ECJ */ Opcodes.ASTORE
- && start.getOpcode() != /* Kotlin */ Opcodes.ALOAD) {
+ if (start.getOpcode() != Opcodes.ASTORE) {
return;
}
+ vars.put("s", (VarInsnNode) start);
cursor = start;
+ JumpInsnNode ifNullInstruction = null;
+ if (start.getNext().getOpcode() == Opcodes.ALOAD) {
+ // Kotlin
+ nextIsVar(Opcodes.ALOAD, "s");
+ if (cursor == null) {
+ return;
+ } else if (cursor.getNext().getOpcode() == Opcodes.DUP) {
+ // nullable case
+ nextIs(Opcodes.DUP);
+ nextIs(Opcodes.IFNULL);
+ ifNullInstruction = (JumpInsnNode) cursor;
+ } else if (cursor.getNext().getOpcode() == Opcodes.IFNULL) {
+ // nullable else
+ nextIs(Opcodes.IFNULL);
+ ifNullInstruction = (JumpInsnNode) cursor;
+ nextIsVar(Opcodes.ALOAD, "s");
+ }
+ }
nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
"()I");
nextIsSwitch();
if (cursor == null) {
return;
}
- vars.put("s", (VarInsnNode) start);
final AbstractInsnNode s = cursor;
final int hashCodes;
@@ -102,8 +118,12 @@ public void match(final AbstractInsnNode start,
}
}
- output.ignore(s.getNext(), cursor);
- output.replaceBranches(s, replacements);
+ if (ifNullInstruction != null) {
+ replacements.add(skipNonOpcodes(ifNullInstruction.label));
+ }
+
+ output.ignore(start.getNext(), cursor);
+ output.replaceBranches(start, replacements);
}
}
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index e098ee6d0d..f3b316c087 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -49,6 +49,10 @@
New Features
expressions and statements with nullable enum subject is filtered out during
generation of report
(GitHub #1774).
+
Part of bytecode generated by the Kotlin compiler for when
+ expressions and statements with nullable String subject is filtered out during
+ generation of report
+ (GitHub #1769).
Part of bytecode generated by the Kotlin compiler for chains of safe call
operators is filtered out during generation of report
(GitHub #1810).
The minimum supported JRE version for JaCoCo is Java 5. To guarantee
compatibility JaCoCo release builds should always be executed using JDK 5.
In addition we run builds with 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
- 18, 19, 20, 21, 22 and 23 JDKs.
+ 18, 19, 20, 21, 22, 23, 24 and 25 JDKs.