From 06c20434dcc758e5586429240fe0c08319024945 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sat, 14 Oct 2023 21:29:59 +0200 Subject: [PATCH 001/255] Prepare for next development iteration --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 33 insertions(+), 31 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index 5b0b74dee7..9a45109d6d 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index ba48a621bf..05e4df8304 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index 43fc89b537..cd6785de12 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index 2391e4de11..45851db9f5 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index af036bf8e7..86f7ff343f 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index 75c522d6e9..d1b938d8c5 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index fd14c7ecd4..537578a72a 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index ed355cb967..dda5068fbc 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index 0cb2c10269..b950ef3810 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index dfd66588ae..7fff8cf6df 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index 71e110325d..ea90b9043a 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 51cf84a6e1..335d116838 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index 8c5bb3798b..ca82aaa365 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index 3eb2fc43a4..c12d234106 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index a3fe029fdd..5fbe15f79c 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index e0f9d8aa8b..34b2d2c793 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index 11b8069b0d..0a60b72593 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 82cf423c25..9f60990488 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index 5e5b0402ec..e8e085d3b7 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 6ec4b02005..d21876c841 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index 5e4162fa8e..a3745ccf89 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 2aaf015d85..b386c70603 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index aa1ee56c73..f19643d865 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index c82ae2fb9a..f90ad53ece 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 4de907fa8d..8f6e274121 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,6 +18,8 @@

Change History

+

Snapshot Build @qualified.bundle.version@ (@build.date@)

+

Release 0.8.11 (2023/10/14)

New Features

diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index a34e093277..5aa3fd9721 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index 8730473532..fba4f2b92b 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index 3abd0dda17..b4d9afb5d9 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index bdfdab48cb..b560c87e8e 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index 37ca48c767..206c4d1b41 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index 5bda469a58..862b045952 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.11 + 0.8.12-SNAPSHOT ../org.jacoco.build diff --git a/pom.xml b/pom.xml index f603485b49..1f88a8b0dd 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.11 + 0.8.12-SNAPSHOT pom From eea740644aac4395cd755f350e3565a4f59e1e39 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 17 Oct 2023 15:30:47 +0200 Subject: [PATCH 002/255] Use SPDX identifier for license declaration in pom.xml (#1529) As recommended by https://maven.apache.org/pom.html#Licenses --- 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 7fff8cf6df..676adba3ea 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -27,7 +27,7 @@ - Eclipse Public License 2.0 + EPL-2.0 https://www.eclipse.org/legal/epl-2.0/ repo From f732fe5d32e6344da03e33e225115467804b463b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:44:45 +0100 Subject: [PATCH 003/255] Fix misleading outdated javadoc (#1532) Outdated since created in commit 88802a1de70be3fbf7675316f0f66b10f5ff34b4 in JaCoCo version 0.3.3 --- org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java b/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java index c1b08d105f..f557f5c554 100644 --- a/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java +++ b/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java @@ -21,8 +21,7 @@ /** * Simple test target for Java applications ant JUnit4 tests. To assert - * execution it creates an empty file target.txt in the working - * directory. + * execution it prints "Target executed". */ public class TestTarget { From 3da12ed4a795d8fdcfb8932f7e1d02566b47a4f1 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 5 Nov 2023 01:57:24 -0800 Subject: [PATCH 004/255] Add reference to JaCoCo extension for bld (#1535) --- org.jacoco.doc/docroot/doc/integrations.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org.jacoco.doc/docroot/doc/integrations.html b/org.jacoco.doc/docroot/doc/integrations.html index 56ed9cb7a2..7eb10f8fbe 100644 --- a/org.jacoco.doc/docroot/doc/integrations.html +++ b/org.jacoco.doc/docroot/doc/integrations.html @@ -84,6 +84,10 @@

Third-Party Integrations

Azure DevOps Cloud-powered collaboration tools by Microsoft, see documentation + + bld + Pure Java build System with JaCoCo extension, see documentation + Codacy Platform to track code coverage and code quality, see documentation From a2ca31a7e86ee540f0aeb45cea911387e427f327 Mon Sep 17 00:00:00 2001 From: Pasha Finkelshteyn Date: Sun, 5 Nov 2023 11:22:13 +0100 Subject: [PATCH 005/255] Add common use cases of questions/problems to README (#1526) --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d2886deb6a..37ea54b772 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ JaCoCo Java Code Coverage Library [![Maven Central](https://img.shields.io/maven-central/v/org.jacoco/jacoco.svg)](http://search.maven.org/#search|ga|1|g%3Aorg.jacoco) JaCoCo is a free Java code coverage library distributed under the Eclipse Public -License. Check the [project homepage](http://www.jacoco.org/jacoco) -for downloads, documentation and feedback. +License. -Please use our [mailing list](https://groups.google.com/forum/?fromgroups=#!forum/jacoco) -for questions regarding JaCoCo which are not already covered by the -[extensive documentation](http://www.jacoco.org/jacoco/trunk/doc/). +## Starting Points -Note: We do not answer general questions in the project's issue tracker. Please use our [mailing list](https://groups.google.com/forum/?fromgroups=#!forum/jacoco) for this. -------------------------------------------------------------------------- +* I want to use JaCoCo → [Download](https://www.jacoco.org/jacoco/), [Maven](https://www.jacoco.org/jacoco/trunk/doc/maven.html), [Ant](https://www.jacoco.org/jacoco/trunk/doc/ant.html), [CLI](https://www.jacoco.org/jacoco/trunk/doc/cli.html), [Other](https://www.jacoco.org/jacoco/trunk/doc/integrations.html) +* I want to know how JaCoCo works → [Documentation](http://www.jacoco.org/jacoco/trunk/doc/) +* I have a question → [FAQ](http://www.jacoco.org/jacoco/trunk/doc/faq.html), [Documentation](http://www.jacoco.org/jacoco/trunk/doc/), [User Forum](https://groups.google.com/forum/?fromgroups=#!forum/jacoco) +* I found a bug → [Bug Report](https://github.com/jacoco/jacoco/issues/new/choose) +* I have an idea → [User Forum](https://groups.google.com/forum/?fromgroups=#!forum/jacoco), [Feature Request](https://github.com/jacoco/jacoco/issues/new/choose) From cf171f8fe1970e2f46bab500e8d5e9bc9d424f3a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 9 Nov 2023 18:22:07 +0100 Subject: [PATCH 006/255] Fix warnings reported by maven-shade-plugin (#1540) --- org.jacoco.agent.rt/pom.xml | 12 ++++++++++++ org.jacoco.ant/pom.xml | 24 ++++++++++++++++++++++++ org.jacoco.cli/pom.xml | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index 86f7ff343f..f8f7c6597c 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -70,6 +70,18 @@ + + *:* + + META-INF/MANIFEST.MF + + + + org.jacoco:org.jacoco.core + + about.html + + org.ow2.asm:* diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index b950ef3810..5b78ef5906 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -69,6 +69,30 @@ + + *:* + + META-INF/MANIFEST.MF + + + + org.jacoco:org.jacoco.core + + about.html + + + + org.jacoco:org.jacoco.report + + about.html + + + + org.jacoco:org.jacoco.agent + + about.html + + org.ow2.asm:* diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 335d116838..db3cb9b512 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -107,6 +107,24 @@ + + *:* + + META-INF/MANIFEST.MF + + + + org.jacoco:org.jacoco.core + + about.html + + + + org.jacoco:org.jacoco.report + + about.html + + args4j:args4j From 717759caab76ac414122b9967e806c06a565a7b1 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 9 Nov 2023 21:21:19 +0100 Subject: [PATCH 007/255] Upgrade ECJ to 3.35.0 (#1538) --- 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 676adba3ea..117c1aaa35 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -945,7 +945,7 @@ org.eclipse.jdt ecj - 3.34.0 + 3.35.0 org.codehaus.plexus From 78647f6f9c02eb7f7b9920b54b38a0517445ee42 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 9 Nov 2023 21:56:10 +0100 Subject: [PATCH 008/255] Upgrade spotless-maven-plugin to 2.40.0 and Eclipse JDT Formatter to 4.29 (#1539) --- org.jacoco.build/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 117c1aaa35..595648d085 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -461,7 +461,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.37.0 + 2.40.0 @@ -554,7 +554,7 @@ src/**/*.java - 4.28 + 4.29 ../org.jacoco.core/.settings/org.eclipse.jdt.core.prefs From 962b3fa4dab8f541f2a94096793a59b638f97130 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 9 Nov 2023 22:26:27 +0100 Subject: [PATCH 009/255] Use spotless-maven-plugin to maintain the order of import statements (#1536) --- org.jacoco.build/pom.xml | 4 ++++ .../analysis/filter/ExhaustiveSwitchFilterTest.java | 6 +++--- .../src/org/jacoco/core/test/InstrumentingLoaderTest.java | 4 ++-- .../org/jacoco/core/test/validation/JavaVersionTest.java | 4 ++-- .../internal/analysis/filter/ExhaustiveSwitchFilter.java | 6 +++--- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 595648d085..8164b8a2a9 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -557,6 +557,10 @@ 4.29 ../org.jacoco.core/.settings/org.eclipse.jdt.core.prefs + + java,javax,org,com, + true + diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java index 20620fffdb..ec6c162b6c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java @@ -12,6 +12,9 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; +import java.util.HashSet; +import java.util.Set; + import org.jacoco.core.internal.instr.InstrSupport; import org.junit.Test; import org.objectweb.asm.Label; @@ -19,9 +22,6 @@ import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.MethodNode; -import java.util.HashSet; -import java.util.Set; - /** * Unit tests for {@link ExhaustiveSwitchFilter}. */ diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoaderTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoaderTest.java index 028cc4d46d..8fe19d478d 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoaderTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoaderTest.java @@ -12,10 +12,10 @@ *******************************************************************************/ package org.jacoco.core.test; -import org.junit.Test; - import static org.junit.Assert.assertSame; +import org.junit.Test; + /** * Unit test for {@link InstrumentingLoader}. */ diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java index c599a5430a..43294009e0 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java @@ -12,12 +12,12 @@ *******************************************************************************/ package org.jacoco.core.test.validation; -import org.junit.Test; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import org.junit.Test; + public class JavaVersionTest { @Test diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java index 4a5e90f3d7..f3b074052f 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java @@ -12,6 +12,9 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; +import java.util.HashSet; +import java.util.List; + import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.LabelNode; @@ -21,9 +24,6 @@ import org.objectweb.asm.tree.TableSwitchInsnNode; import org.objectweb.asm.tree.TypeInsnNode; -import java.util.HashSet; -import java.util.List; - /** * Filters default branch generated by compilers for exhaustive switch * expressions. From 4bcc43f53b13c9b8ef7ae5100f25468392448f7d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:32:02 +0100 Subject: [PATCH 010/255] Add experimental support for Java 23 class files (#1553) --- .azure-pipelines/azure-pipelines.yml | 2 ++ org.jacoco.build/pom.xml | 14 ++++++++ org.jacoco.core.test.validation/pom.xml | 33 +++++++++++++++++++ .../jacoco/core/analysis/AnalyzerTest.java | 10 +++--- .../jacoco/core/instr/InstrumenterTest.java | 10 +++--- .../core/internal/instr/InstrSupportTest.java | 15 +++++---- .../core/internal/instr/InstrSupport.java | 4 +-- org.jacoco.doc/docroot/doc/changes.html | 6 ++++ 8 files changed, 75 insertions(+), 19 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index da3f52c61f..7369d565a0 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -47,6 +47,8 @@ jobs: JDK_VERSION: 21 JDK 22: JDK_VERSION: 22 + JDK 23: + JDK_VERSION: 23 pool: vmImage: 'ubuntu-20.04' steps: diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 8164b8a2a9..1a97c3067f 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -929,6 +929,20 @@ + + java23-bytecode + + + bytecode.version + 23 + + + + 13 + 13 + + + ecj diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index b386c70603..923b37229d 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -488,6 +488,39 @@
+ + java23-bytecode + + + bytecode.version + 23 + + + + + 16 + + 16 + + 23 + 23 + + + ../org.jacoco.core.test.validation.kotlin + ../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 + + + + + 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 54d1a165c7..3e2e7c3bdb 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 @@ -109,7 +109,7 @@ public void should_ignore_synthetic_classes() throws Exception { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V21 + 1); + final byte[] originalBytes = createClass(Opcodes.V22 + 1); final byte[] bytes = new byte[originalBytes.length]; System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length); final long expectedClassId = CRC64.classId(bytes); @@ -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.V21 + 2); + final byte[] bytes = createClass(Opcodes.V22 + 2); try { analyzer.analyzeClass(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 67", + assertEquals("Unsupported class file major version 68", 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.V21 + 2); + final byte[] bytes = createClass(Opcodes.V22 + 2); try { analyzer.analyzeAll(new ByteArrayInputStream(bytes), "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 67", + assertEquals("Unsupported class file major version 68", e.getCause().getMessage()); } } 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 7df3e6dd11..e6c70fcbf4 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 @@ -100,7 +100,7 @@ public void setup() throws Exception { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V21 + 1); + final byte[] originalBytes = createClass(Opcodes.V22 + 1); final byte[] bytes = new byte[originalBytes.length]; System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length); final long expectedClassId = CRC64.classId(bytes); @@ -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.V21 + 2); + final byte[] bytes = createClass(Opcodes.V22 + 2); try { instrumenter.instrument(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (final IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 67", + assertEquals("Unsupported class file major version 68", 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.V21 + 2); + final byte[] bytes = createClass(Opcodes.V22 + 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 67", + assertEquals("Unsupported class file major version 68", 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 f57a981e99..d11ea60c8f 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_22_class() { - final byte[] bytes = createJava22Class(); + public void classReaderFor_should_read_java_23_class() { + final byte[] bytes = createJava23Class(); final ClassReader classReader = InstrSupport.classReaderFor(bytes); @@ -53,16 +53,16 @@ public void classReaderFor_should_read_java_22_class() { public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { - assertEquals(Opcodes.V21 + 1, version); + assertEquals(Opcodes.V22 + 1, version); } }, 0); - assertArrayEquals(createJava22Class(), bytes); + assertArrayEquals(createJava23Class(), bytes); } - private static byte[] createJava22Class() { + private static byte[] createJava23Class() { final ClassWriter cw = new ClassWriter(0); - cw.visit(Opcodes.V21 + 1, 0, "Foo", null, "java/lang/Object", null); + cw.visit(Opcodes.V22 + 1, 0, "Foo", null, "java/lang/Object", null); cw.visitEnd(); return cw.toByteArray(); } @@ -133,7 +133,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_ assertTrue(InstrSupport.needsFrames(Opcodes.V19)); assertTrue(InstrSupport.needsFrames(Opcodes.V20)); assertTrue(InstrSupport.needsFrames(Opcodes.V21)); - assertTrue(InstrSupport.needsFrames(Opcodes.V21 + 1)); + assertTrue(InstrSupport.needsFrames(Opcodes.V22)); + assertTrue(InstrSupport.needsFrames(Opcodes.V22 + 1)); assertTrue(InstrSupport.needsFrames(0x0100)); } 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 2f8bbda7f6..00707422c5 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.V21 + 1) { + if (originalVersion == Opcodes.V22 + 1) { // temporarily downgrade version to bypass check in ASM - setMajorVersion(Opcodes.V21, b); + setMajorVersion(Opcodes.V22, 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 8f6e274121..1d0b56df81 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -20,6 +20,12 @@

Change History

Snapshot Build @qualified.bundle.version@ (@build.date@)

+

New Features

+ +

Release 0.8.11 (2023/10/14)

New Features

From ac138508533a5fbfdde9935ca3782eacc1c85608 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 13 Dec 2023 09:46:21 +0100 Subject: [PATCH 011/255] Upgrade spotless-maven-plugin to 2.41.1 and Eclipse JDT Formatter to 4.30 (#1554) --- org.jacoco.build/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 1a97c3067f..2c13da9036 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -461,7 +461,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.40.0 + 2.41.1 @@ -554,7 +554,7 @@ src/**/*.java - 4.29 + 4.30 ../org.jacoco.core/.settings/org.eclipse.jdt.core.prefs From b12797176bf986d92c59c7bd32edec63bab14812 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:29:05 +0100 Subject: [PATCH 012/255] Upgrade ECJ to 3.36.0 (#1555) --- .azure-pipelines/azure-pipelines.yml | 6 +++--- org.jacoco.build/pom.xml | 2 +- .../core/test/validation/java21/RecordPatternsTest.java | 9 +++++++++ .../validation/java21/targets/RecordPatternsTarget.java | 2 +- org.jacoco.doc/docroot/doc/build.html | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index 7369d565a0..7ad536ee6b 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -40,11 +40,11 @@ jobs: JDK_VERSION: 19 JDK 20: JDK_VERSION: 20 - JDK 20 with ECJ: - JDK_VERSION: 20 - ECJ: true JDK 21: JDK_VERSION: 21 + JDK 21 with ECJ: + JDK_VERSION: 21 + ECJ: true JDK 22: JDK_VERSION: 22 JDK 23: diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 2c13da9036..1dcda98fea 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -963,7 +963,7 @@ org.eclipse.jdt ecj - 3.35.0 + 3.36.0 org.codehaus.plexus diff --git a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java index 629675e4dc..da53b58494 100644 --- a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java +++ b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java @@ -26,4 +26,13 @@ public RecordPatternsTest() { super(RecordPatternsTarget.class); } + public void assertSwitchStatementLastCase(final Line line) { + if (isJDKCompiler) { + assertFullyCovered(line); + } else { + // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773 + assertPartlyCovered(line); + } + } + } diff --git a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/targets/RecordPatternsTarget.java b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/targets/RecordPatternsTarget.java index d129b4cc2e..99a6a99ccc 100644 --- a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/targets/RecordPatternsTarget.java +++ b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/targets/RecordPatternsTarget.java @@ -31,7 +31,7 @@ private static void instanceofOperator(Object o) { private static void switchStatement(Object p) { switch (p) { // assertFullyCovered(0, 2) - case Point(int x, int y) -> nop(x + y); // assertFullyCovered() + case Point(int x, int y) -> nop(x + y); // assertSwitchStatementLastCase() default -> nop(); // assertFullyCovered() } // assertEmpty() } diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index 77a278d7c9..ef7297d4d1 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -329,8 +329,8 @@

Compilation and testing with different JDKs

  • mvn clean verify -Djdk.version=18 -Dbytecode.version=18
  • mvn clean verify -Djdk.version=19 -Dbytecode.version=19
  • mvn clean verify -Djdk.version=20 -Dbytecode.version=20
  • -
  • mvn clean verify -Djdk.version=20 -Dbytecode.version=20 -Decj
  • mvn clean verify -Djdk.version=21 -Dbytecode.version=21
  • +
  • mvn clean verify -Djdk.version=20 -Dbytecode.version=21 -Decj
  • From eb30f1758d7ec48da14e3b7a9e75e7f9cd2ee643 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:28:28 +0100 Subject: [PATCH 013/255] Fix KotlinDefaultArgumentsFilter for the case of more than 32 parameters (#1556) --- .../targets/KotlinDefaultArgumentsTarget.kt | 43 +++++ .../KotlinDefaultArgumentsFilterTest.java | 147 ++++++++++++++++++ .../filter/KotlinDefaultArgumentsFilter.java | 38 +++-- org.jacoco.doc/docroot/doc/changes.html | 7 + 4 files changed, 224 insertions(+), 11 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt index d619bc3443..9befa9c429 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt @@ -35,6 +35,42 @@ object KotlinDefaultArgumentsTarget { constructor(a: Boolean, b: String = if (a) "a" else "b") : this() // assertFullyCovered(0, 2) } + class MoreThan32Parameters( // assertFullyCovered() + p1: String, // assertEmpty() + p2: String, // assertEmpty() + p3: String, // assertEmpty() + p4: String, // assertEmpty() + p5: String, // assertEmpty() + p6: String, // assertEmpty() + p7: String, // assertEmpty() + p8: String, // assertEmpty() + p9: String, // assertEmpty() + p10: String, // assertEmpty() + p11: String, // assertEmpty() + p12: String, // assertEmpty() + p13: String, // assertEmpty() + p14: String, // assertEmpty() + p15: String, // assertEmpty() + p16: String, // assertEmpty() + p17: String, // assertEmpty() + p18: String, // assertEmpty() + p19: String, // assertEmpty() + p20: String, // assertEmpty() + p21: String, // assertEmpty() + p22: String, // assertEmpty() + p23: String, // assertEmpty() + p24: String, // assertEmpty() + p25: String, // assertEmpty() + p26: String, // assertEmpty() + p27: String, // assertEmpty() + p28: String, // assertEmpty() + p29: String, // assertEmpty() + p30: String, // assertEmpty() + p31: String, // assertEmpty() + p32: String = "", // assertFullyCovered() + p33: String, // assertEmpty() + ) // assertFullyCovered() + @JvmStatic fun main(args: Array) { f(a = "a") @@ -52,6 +88,13 @@ object KotlinDefaultArgumentsTarget { Constructor(false) Constructor(true) + + MoreThan32Parameters( + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", + "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", + "31", p33 = "" + ) } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java index cc00e6885e..aeaa4885ee 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java @@ -12,6 +12,8 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; +import static org.junit.Assert.assertEquals; + import org.jacoco.core.internal.instr.InstrSupport; import org.junit.Test; import org.objectweb.asm.Label; @@ -219,4 +221,149 @@ public void should_filter_methods_with_parameters_that_consume_two_slots() { assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); } + /** + *
    +	 * class C(
    +	 *   p1: Int,
    +	 *   ...
    +	 *   p31: Int,
    +	 *   p32: Int = 42,
    +	 *   p33: Int,
    +	 * )
    +	 * 
    + * + * This constructor will have 2 additional parameters containing the mask. + */ + @Test + public void should_filter_methods_with_more_than_32_parameters() { + final StringBuilder paramTypes = new StringBuilder(); + for (int i = 1; i <= 33; i++) { + paramTypes.append("I"); + } + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "", + "(" + paramTypes + + "IILkotlin/jvm/internal/DefaultConstructorMarker;)V", + null, null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + + m.visitVarInsn(Opcodes.ILOAD, 34); + m.visitLdcInsn(Integer.valueOf(1 << 31)); + m.visitInsn(Opcodes.IAND); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFEQ, label); + // default argument + m.visitLdcInsn(Integer.valueOf(42)); + m.visitVarInsn(Opcodes.ISTORE, 32); + m.visitLabel(label); + + m.visitVarInsn(Opcodes.ALOAD, 0); + for (int i = 1; i <= 33; i++) { + m.visitVarInsn(Opcodes.ILOAD, i); + } + m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Owner", "", + "(" + paramTypes + ")V", false); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + } + + /** + *
    +	 * class C(
    +	 *   p1: Int = 42,
    +	 *   ...
    +	 *   p225: Int,
    +	 * )
    +	 * 
    + * + * This constructor will have 8 additional parameters containing the mask. + * + * 9 additional parameters will be required for methods with more than 256 + * parameters, but according to Java Virtual Machine Specification + * §4.11: + * + *
    + *

    + * The number of method parameters is limited to 255 + *

    + *
    + */ + @Test + public void should_filter_methods_with_more_than_224_parameters() { + final StringBuilder paramTypes = new StringBuilder(); + for (int i = 1; i <= 225; i++) { + paramTypes.append("I"); + } + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "", + "(" + paramTypes + + "IIIIIIIILkotlin/jvm/internal/DefaultConstructorMarker;)V", + null, null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + + m.visitVarInsn(Opcodes.ILOAD, 226); + m.visitInsn(Opcodes.ICONST_1); + m.visitInsn(Opcodes.IAND); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFEQ, label); + // default argument + m.visitLdcInsn(Integer.valueOf(42)); + m.visitVarInsn(Opcodes.ISTORE, 1); + m.visitLabel(label); + + m.visitVarInsn(Opcodes.ALOAD, 0); + for (int i = 1; i <= 225; i++) { + m.visitVarInsn(Opcodes.ILOAD, i); + } + m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Owner", "", + "(" + paramTypes + ")V", false); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + } + + @Test + public void computeNumberOfMaskArguments() { + assertEquals(1, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(3)); + assertEquals(1, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(34)); + assertEquals(2, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(36)); + assertEquals(2, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(67)); + assertEquals(3, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(69)); + assertEquals(3, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(100)); + assertEquals(4, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(102)); + assertEquals(4, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(133)); + assertEquals(5, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(135)); + assertEquals(5, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(166)); + assertEquals(6, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(168)); + assertEquals(6, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(199)); + assertEquals(7, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(201)); + assertEquals(7, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(232)); + assertEquals(8, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(234)); + assertEquals(8, + KotlinDefaultArgumentsFilter.computeNumberOfMaskArguments(255)); + } + } 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 f83167c3d7..e9d53d51a9 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 @@ -26,8 +26,11 @@ /** * Filters branches that Kotlin compiler generates for default arguments. * - * For each default argument Kotlin compiler generates following bytecode to - * determine if it should be used or not: + * For methods and constructors with default arguments Kotlin compiler generates + * synthetic method with suffix "$default" or a synthetic constructor with last + * argument "kotlin.jvm.internal.DefaultConstructorMarker" respectively. And in + * this synthetic method for each default argument Kotlin compiler generates + * following bytecode to determine if it should be used or not: * *
      * ILOAD maskVar
    @@ -38,11 +41,14 @@
      * label:
      * 
    * - * Where maskVar is penultimate argument of synthetic method with - * suffix "$default" or of synthetic constructor with last argument - * "kotlin.jvm.internal.DefaultConstructorMarker". And its value can't be zero - - * invocation with all arguments uses original non synthetic method, thus - * IFEQ instructions should be ignored. + * If original method has X arguments, then in synthetic method + * maskVar is one of arguments from X+1 to + * X+1+(X/32). + * + * At least one of such arguments is not zero - invocation without default + * arguments uses original non synthetic method. + * + * This filter marks IFEQ instructions as ignored. */ public final class KotlinDefaultArgumentsFilter implements IFilter { @@ -132,19 +138,29 @@ public void match(final MethodNode methodNode, private static int maskVar(final String desc, final boolean constructor) { + final Type[] argumentTypes = Type.getMethodType(desc) + .getArgumentTypes(); int slot = 0; if (constructor) { // one slot for reference to current object slot++; } - final Type[] argumentTypes = Type.getMethodType(desc) - .getArgumentTypes(); - final int penultimateArgument = argumentTypes.length - 2; - for (int i = 0; i < penultimateArgument; i++) { + final int firstMaskArgument = argumentTypes.length - 1 + - computeNumberOfMaskArguments(argumentTypes.length); + for (int i = 0; i < firstMaskArgument; i++) { slot += argumentTypes[i].getSize(); } return slot; } } + /** + * @param arguments + * number of arguments of synthetic method + * @return number of arguments holding mask + */ + static int computeNumberOfMaskArguments(final int arguments) { + return (arguments - 2) / 33 + 1; + } + } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 1d0b56df81..90b0340f97 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -26,6 +26,13 @@

    New Features

    (GitHub #1553). +

    Fixed bugs

    +
      +
    • Branches added by the Kotlin compiler for functions with default arguments and + having more than 32 parameters are filtered out during generation of report + (GitHub #1556).
    • +
    +

    Release 0.8.11 (2023/10/14)

    New Features

    From 59d4004065c27e09f795c6a18a3581f4bc51be18 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:39:01 +0100 Subject: [PATCH 014/255] Add Skippy to the list of third-party integrations (#1564) --- org.jacoco.doc/docroot/doc/integrations.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org.jacoco.doc/docroot/doc/integrations.html b/org.jacoco.doc/docroot/doc/integrations.html index 7eb10f8fbe..08d2e7ea39 100644 --- a/org.jacoco.doc/docroot/doc/integrations.html +++ b/org.jacoco.doc/docroot/doc/integrations.html @@ -137,6 +137,10 @@

    Third-Party Integrations

    Shippable Continuous integration and delivery platform, see documentation + + Skippy + Test Impact Analysis & Predictive Test Selection framework for the JVM, see documentation + SonarQube Continuous inspection platform with JaCoCo support, see documentation From de91a3fba7ff6cd2c145cff3a63080624694fc2a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:03:25 +0100 Subject: [PATCH 015/255] `execute_assertions_in_comments` should show all failed assertions instead of just first (#1565) --- .../core/test/validation/java5/FinallyTest.java | 2 +- .../core/test/validation/ValidationTestBase.java | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java index 632128ea30..933fd7b3b6 100644 --- a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java +++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java @@ -127,7 +127,7 @@ public void assertAlwaysCompletesAbruptly1(final Line line) { @Test @Override - public void execute_assertions_in_comments() throws IOException { + public void execute_assertions_in_comments() throws Exception { super.execute_assertions_in_comments(); gotos(); } 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 86758e9f38..c8a39a640d 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.IOException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import org.jacoco.core.analysis.Analyzer; @@ -32,6 +33,7 @@ import org.jacoco.core.test.validation.targets.Stubs; import org.junit.Before; import org.junit.Test; +import org.junit.runners.model.MultipleFailureException; /** * Base class for validation tests. It executes the given class under code @@ -103,14 +105,20 @@ private void analyze(final Analyzer analyzer, final ExecutionData data) * */ @Test - public void execute_assertions_in_comments() throws IOException { + public void execute_assertions_in_comments() throws Exception { + final ArrayList failedAssertions = new ArrayList(); for (Line line : source.getLines()) { String exec = line.getComment(); if (exec != null) { - StatementParser.parse(exec, new StatementExecutor(this, line), - line.toString()); + try { + StatementParser.parse(exec, + new StatementExecutor(this, line), line.toString()); + } catch (final AssertionError e) { + failedAssertions.add(e); + } } } + MultipleFailureException.assertEmpty(failedAssertions); } /** From f8a0a9e7bd4697538d5b65ed9d29be10872f5531 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:19:25 +0100 Subject: [PATCH 016/255] Upgrade Groovy to 3.0.20 (#1570) --- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index ca82aaa365..b934af32a0 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.19 + 3.0.20 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 923b37229d..cc13e1d17d 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -351,7 +351,7 @@ 16 - + 16 18 @@ -379,7 +379,7 @@ 16 - + 16 19 @@ -407,7 +407,7 @@ 16 - + 16 20 @@ -435,7 +435,7 @@ 16 - + 16 21 @@ -466,7 +466,7 @@ 16 - + 16 22 @@ -479,7 +479,7 @@ ../org.jacoco.core.test.validation.java14 ../org.jacoco.core.test.validation.java16 ../org.jacoco.core.test.validation.java21 - 16 - + 16 23 @@ -512,7 +512,7 @@ ../org.jacoco.core.test.validation.java14 ../org.jacoco.core.test.validation.java16 ../org.jacoco.core.test.validation.java21 - @@ -482,9 +480,7 @@ - @@ -515,9 +511,7 @@ - From 2b9c1a4c2ae25e74833d1c2b2a12b500d4456243 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:00:55 +0100 Subject: [PATCH 027/255] Upgrade maven-javadoc-plugin to 3.6.3 (#1455) --- org.jacoco.build/pom.xml | 6 +----- org.jacoco.doc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 1dcda98fea..586bc61ce4 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -352,11 +352,7 @@ org.apache.maven.plugins maven-javadoc-plugin - - 3.0.1 + 3.6.3 true false diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index 5aa3fd9721..3e161a8471 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -200,7 +200,7 @@ ${project.build.directory}/apidocs true - *.internal,org.jacoco.ant,org.jacoco.maven,org.jacoco.examples + *.internal.*,*.internal,org.jacoco.ant,org.jacoco.maven,org.jacoco.examples org.jacoco:* From fd872de13cbac0fa6c813f95fd0421a4ba4e9b67 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 25 Feb 2024 17:13:51 +0100 Subject: [PATCH 028/255] Add missing java13-bytecode profile (#1584) --- org.jacoco.core.test.validation/pom.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index e8c2e91267..e92a9e57a0 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -237,6 +237,30 @@ + + java13-bytecode + + + bytecode.version + 13 + + + + 13 + 13 + + 13 + 13 + + + ../org.jacoco.core.test.validation.kotlin + ../org.jacoco.core.test.validation.java7 + ../org.jacoco.core.test.validation.java8 + ../org.jacoco.core.test.validation.groovy + ../org.jacoco.core.test.validation.scala + + + java14-bytecode From 35f352a95551f532da9013f3587e2591cdcef6ec Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Tue, 5 Mar 2024 10:19:31 +0100 Subject: [PATCH 029/255] Happy New Year 2024! --- LICENSE.md | 2 +- jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml | 2 +- .../it/it-check-fails-halt/src/main/java/Example.java | 2 +- .../it/it-check-fails-halt/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml | 2 +- .../it/it-check-fails-no-halt/src/main/java/Example.java | 2 +- .../it-check-fails-no-halt/src/test/java/ExampleTest.java | 2 +- .../it/it-check-fails-no-halt/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-check-passes/pom.xml | 2 +- .../it/it-check-passes/src/main/java/Example.java | 2 +- .../it/it-check-passes/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-check-passes/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-customize-agent/pom.xml | 2 +- .../it/it-customize-agent/src/main/java/Example.java | 2 +- .../it/it-customize-agent/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-dump/pom.xml | 2 +- .../it/it-dump/src/main/java/Server.java | 2 +- jacoco-maven-plugin.test/it/it-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml | 2 +- .../src/main/java/org/project/DatabaseUtil.java | 2 +- .../src/main/java/org/project/FileUtil.java | 2 +- .../src/main/java/org/project/TestUtil.java | 2 +- .../src/test/java/org/project/TestDatabaseUtil.java | 2 +- jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh | 2 +- .../it/it-java9-offline-instrumentation/pom.xml | 2 +- .../src/main/java/module-info.java | 2 +- .../src/main/java/org/example/Example.java | 2 +- .../src/test/java/org/example/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-java9/pom.xml | 2 +- .../it/it-java9/src/main/java/Example.java | 2 +- .../it/it-java9/src/test/java/ExampleTest.java | 2 +- .../it/it-merge-passes/it-merge-passes-merge/pom.xml | 2 +- .../it/it-merge-passes/it-merge-passes-project1/pom.xml | 2 +- .../it-merge-passes-project1/src/main/java/Example.java | 2 +- .../it-merge-passes-project1/src/test/java/ExampleTest.java | 2 +- .../it/it-merge-passes/it-merge-passes-project2/pom.xml | 2 +- .../it-merge-passes-project2/src/main/java/Example.java | 2 +- .../it-merge-passes-project2/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-merge-passes/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh | 2 +- .../it/it-multi-module/child-jar-without-sources/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml | 2 +- .../it/it-multi-module/child/src/main/java/Example.java | 2 +- .../child/src/main/java/somepackage/Example.java | 2 +- .../it/it-multi-module/child/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-multi-module/pom.xml | 2 +- .../it/it-multi-module/skip-child/pom.xml | 2 +- .../it/it-multi-module/skip-child/src/test/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-multi-module/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml | 2 +- .../it/it-multiple-executions/src/main/java/Example.java | 2 +- .../it-multiple-executions/src/test/java/ExampleTest.java | 2 +- .../it/it-multiple-executions/verify.bsh | 2 +- .../child-without-main-classes/pom.xml | 2 +- .../src/test/java/ExampleTest.java | 2 +- .../it/it-offline-instrumentation/child/pom.xml | 2 +- .../child/src/main/java/DoNotInstrument.java | 2 +- .../child/src/main/java/Example.java | 2 +- .../child/src/test/java/ExampleTest.java | 2 +- .../it/it-offline-instrumentation/pom.xml | 2 +- .../it/it-offline-instrumentation/verify.bsh | 2 +- .../it/it-prepend-property-skip/pom.xml | 2 +- .../it-prepend-property-skip/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-prepend-property/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh | 2 +- .../it/it-report-aggregate-customization/child1/pom.xml | 2 +- .../child1/src/main/java/package1/Example1.java | 2 +- .../child1/src/test/java/package1/Example1Test.java | 2 +- .../it/it-report-aggregate-customization/child2/pom.xml | 2 +- .../child2/src/main/java/package2/Example2.java | 2 +- .../child2/src/test/java/package2/Example2Test.java | 2 +- .../it/it-report-aggregate-customization/pom.xml | 2 +- .../it/it-report-aggregate-customization/report/pom.xml | 2 +- .../it/it-report-aggregate-customization/verify.bsh | 2 +- .../it/it-report-aggregate/child1-test/pom.xml | 2 +- .../child1-test/src/test/java/package1/Example1bTest.java | 2 +- .../it/it-report-aggregate/child1/pom.xml | 2 +- .../child1/src/main/java/package1/Example1a.java | 2 +- .../child1/src/main/java/package1/Example1b.java | 2 +- .../child1/src/test/java/package1/Example1aTest.java | 2 +- .../it/it-report-aggregate/child2/pom.xml | 2 +- .../child2/src/main/java/package2/Example2.java | 2 +- .../child2/src/test/java/package2/Example2Test.java | 2 +- .../it/it-report-aggregate/child2v2/pom.xml | 2 +- .../child2v2/src/main/java/package2/Example2.java | 2 +- .../child2v2/src/test/java/package2/Example2Test.java | 2 +- jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml | 2 +- .../it/it-report-aggregate/report/pom.xml | 2 +- .../report/src/test/java/packagereport/ReportTest.java | 2 +- jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml | 2 +- .../it/it-report-nomatch/src/main/java/Example.java | 2 +- jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh | 2 +- .../it/it-report-select-formats/pom.xml | 2 +- .../it/it-report-select-formats/src/main/java/Example.java | 2 +- .../it-report-select-formats/src/test/java/ExampleTest.java | 2 +- .../it/it-report-select-formats/verify.bsh | 2 +- .../it/it-report-unreadable-dump/pom.xml | 2 +- .../it/it-report-unreadable-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml | 2 +- .../it/it-report-without-debug/src/main/java/Example.java | 2 +- .../it-report-without-debug/src/test/java/ExampleTest.java | 2 +- .../it/it-report-without-debug/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml | 2 +- .../it/it-report-without-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml | 2 +- .../it/it-site-failsafe/src/main/java/Example.java | 2 +- .../it/it-site-failsafe/src/test/java/ExampleIT.java | 2 +- .../it/it-site-failsafe/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-site/pom.xml | 2 +- .../it/it-site/src/main/java/Example.java | 2 +- .../it/it-site/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-site/verify.bsh | 2 +- jacoco-maven-plugin.test/it/settings.xml | 2 +- jacoco-maven-plugin.test/it/setup-parent/pom.xml | 2 +- jacoco-maven-plugin.test/pom.xml | 2 +- .../META-INF/m2e/lifecycle-mapping-metadata.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- .../src/org/jacoco/maven/AbstractAgentMojo.java | 2 +- .../src/org/jacoco/maven/AbstractJacocoMojo.java | 2 +- .../src/org/jacoco/maven/AbstractReportMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java | 2 +- .../src/org/jacoco/maven/InstrumentMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java | 2 +- .../src/org/jacoco/maven/ReportAggregateMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportFormat.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java | 2 +- .../src/org/jacoco/maven/RuleConfiguration.java | 2 +- jacoco/assembly.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- .../src/org/jacoco/agent/rt/internal/AgentModuleTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/AgentTest.java | 2 +- .../org/jacoco/agent/rt/internal/ClassFileDumperTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java | 2 +- .../jacoco/agent/rt/internal/CoverageTransformerTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/ExceptionRecorder.java | 2 +- .../jacoco/agent/rt/internal/output/ExecutorTestBase.java | 2 +- .../org/jacoco/agent/rt/internal/output/FileOutputTest.java | 2 +- .../jacoco/agent/rt/internal/output/MockServerSocket.java | 2 +- .../agent/rt/internal/output/MockServerSocketTest.java | 2 +- .../agent/rt/internal/output/MockSocketConnection.java | 2 +- .../agent/rt/internal/output/MockSocketConnectionTest.java | 2 +- .../agent/rt/internal/output/TcpClientOutputTest.java | 2 +- .../jacoco/agent/rt/internal/output/TcpConnectionTest.java | 2 +- .../agent/rt/internal/output/TcpServerOutputTest.java | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java | 2 +- .../src/com/vladium/emma/rt/package-info.java | 2 +- org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java | 2 +- org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java | 2 +- .../src/org/jacoco/agent/rt/internal/Agent.java | 2 +- .../src/org/jacoco/agent/rt/internal/AgentModule.java | 2 +- .../src/org/jacoco/agent/rt/internal/ClassFileDumper.java | 2 +- .../src/org/jacoco/agent/rt/internal/ConfigLoader.java | 2 +- .../org/jacoco/agent/rt/internal/CoverageTransformer.java | 2 +- .../src/org/jacoco/agent/rt/internal/IExceptionLogger.java | 2 +- .../src/org/jacoco/agent/rt/internal/JmxRegistration.java | 2 +- .../src/org/jacoco/agent/rt/internal/Offline.java | 2 +- .../src/org/jacoco/agent/rt/internal/PreMain.java | 2 +- .../src/org/jacoco/agent/rt/internal/output/FileOutput.java | 2 +- .../org/jacoco/agent/rt/internal/output/IAgentOutput.java | 2 +- .../src/org/jacoco/agent/rt/internal/output/NoneOutput.java | 2 +- .../jacoco/agent/rt/internal/output/TcpClientOutput.java | 2 +- .../org/jacoco/agent/rt/internal/output/TcpConnection.java | 2 +- .../jacoco/agent/rt/internal/output/TcpServerOutput.java | 2 +- .../src/org/jacoco/agent/rt/package-info.java | 2 +- org.jacoco.agent.test/pom.xml | 2 +- .../src/org/jacoco/agent/AgentJarTest.java | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.agent/src/org/jacoco/agent/AgentJar.java | 2 +- org.jacoco.agent/src/org/jacoco/agent/package-info.java | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant.test/src/TestTargetInDefault.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml | 2 +- .../src/org/jacoco/ant/AntFilesLocatorTest.java | 2 +- .../src/org/jacoco/ant/AntResourcesLocatorTest.java | 2 +- .../src/org/jacoco/ant/CoverageTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java | 2 +- .../src/org/jacoco/ant/DumpExecClassNames.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml | 2 +- .../src/org/jacoco/ant/DumpTaskWithServerTest.java | 2 +- .../src/org/jacoco/ant/DumpTaskWithServerTest.xml | 2 +- .../src/org/jacoco/ant/IllegalReflectiveAccessTarget.java | 2 +- .../src/org/jacoco/ant/InstrumentTaskTest.java | 2 +- .../src/org/jacoco/ant/InstrumentTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml | 2 +- .../src/org/jacoco/ant/RemoveDebugInfos.java | 2 +- .../src/org/jacoco/ant/ReportTaskLocaleTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AgentTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/DumpTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/MergeTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/ReportTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/antlib.xml | 2 +- org.jacoco.build/pom.xml | 6 +++--- org.jacoco.cli.test/pom.xml | 2 +- .../src/org/jacoco/cli/internal/CommandTestBase.java | 2 +- .../src/org/jacoco/cli/internal/MainTest.java | 2 +- .../src/org/jacoco/cli/internal/XmlDocumentationTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ClassInfoTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/DumpTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ExecInfoTest.java | 2 +- .../org/jacoco/cli/internal/commands/InstrumentTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/MergeTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ReportTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/VersionTest.java | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/Command.java | 2 +- .../src/org/jacoco/cli/internal/CommandHandler.java | 2 +- .../src/org/jacoco/cli/internal/CommandParser.java | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/Main.java | 2 +- .../src/org/jacoco/cli/internal/XmlDocumentation.java | 2 +- .../src/org/jacoco/cli/internal/commands/AllCommands.java | 2 +- .../src/org/jacoco/cli/internal/commands/ClassInfo.java | 2 +- .../src/org/jacoco/cli/internal/commands/Dump.java | 2 +- .../src/org/jacoco/cli/internal/commands/ExecInfo.java | 2 +- .../src/org/jacoco/cli/internal/commands/Instrument.java | 2 +- .../src/org/jacoco/cli/internal/commands/Merge.java | 2 +- .../src/org/jacoco/cli/internal/commands/Report.java | 2 +- .../src/org/jacoco/cli/internal/commands/Version.java | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- .../test/validation/groovy/GroovyAutoCloneClassTest.java | 2 +- .../validation/groovy/GroovyAutoExternalizeClassTest.java | 2 +- .../test/validation/groovy/GroovyBindableClassTest.java | 2 +- .../core/test/validation/groovy/GroovyBuilderClassTest.java | 2 +- .../test/validation/groovy/GroovyCanonicalClassTest.java | 2 +- .../test/validation/groovy/GroovyDelegateClassTest.java | 2 +- .../test/validation/groovy/GroovyImmutableClassTest.java | 2 +- .../validation/groovy/GroovyIndexPropertyClassTest.java | 2 +- .../test/validation/groovy/GroovySortableClassTest.java | 2 +- .../test/validation/groovy/GroovyVetoableClassTest.java | 2 +- .../groovy/targets/GroovyAutoCloneClassTarget.groovy | 2 +- .../groovy/targets/GroovyAutoExternalizeClassTarget.groovy | 2 +- .../groovy/targets/GroovyBindableClassTarget.groovy | 2 +- .../groovy/targets/GroovyBuilderClassTarget.groovy | 2 +- .../groovy/targets/GroovyCanonicalClassTarget.groovy | 2 +- .../groovy/targets/GroovyDelegateClassTarget.groovy | 2 +- .../groovy/targets/GroovyImmutableClassTarget.groovy | 2 +- .../groovy/targets/GroovyIndexPropertyClassTarget.groovy | 2 +- .../groovy/targets/GroovySortableClassTarget.groovy | 2 +- .../groovy/targets/GroovyVetoableClassTarget.groovy | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- .../core/test/validation/java14/SwitchExpressionsTest.java | 2 +- .../validation/java14/targets/SwitchExpressionsTarget.java | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- .../jacoco/core/test/validation/java16/InstanceofTest.java | 2 +- .../org/jacoco/core/test/validation/java16/RecordsTest.java | 2 +- .../test/validation/java16/targets/InstanceofTarget.java | 2 +- .../core/test/validation/java16/targets/RecordsTarget.java | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- .../core/test/validation/java21/RecordPatternsTest.java | 2 +- .../test/validation/java21/SwitchPatternMatchingTest.java | 2 +- .../validation/java21/targets/RecordPatternsTarget.java | 2 +- .../java21/targets/SwitchPatternMatchingTarget.java | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- .../core/test/validation/java5/AnnotationGeneratedTest.java | 2 +- .../test/validation/java5/AnnotationInitializerTest.java | 2 +- .../org/jacoco/core/test/validation/java5/AssertTest.java | 2 +- .../core/test/validation/java5/BadCycleClassTest.java | 2 +- .../core/test/validation/java5/BooleanExpressionsTest.java | 2 +- .../core/test/validation/java5/ClassInitializerTest.java | 2 +- .../jacoco/core/test/validation/java5/ConstructorsTest.java | 2 +- .../java5/ControlStructureBeforeSuperConstructorTest.java | 2 +- .../core/test/validation/java5/ControlStructuresTest.java | 2 +- .../test/validation/java5/CyclomaticComplexityTest.java | 2 +- .../core/test/validation/java5/EnumConstructorTest.java | 2 +- .../core/test/validation/java5/EnumImplicitMethodsTest.java | 2 +- .../jacoco/core/test/validation/java5/EnumSwitchTest.java | 2 +- .../jacoco/core/test/validation/java5/ExceptionsTest.java | 2 +- .../test/validation/java5/ExplicitInitialFrameTest.java | 2 +- .../java5/FieldInitializationInTwoConstructorsTest.java | 2 +- .../org/jacoco/core/test/validation/java5/FinallyTest.java | 2 +- .../org/jacoco/core/test/validation/java5/FramesTest.java | 2 +- .../validation/java5/ImplicitFieldInitializationTest.java | 2 +- .../validation/java5/InterfaceClassInitializerTest.java | 2 +- .../core/test/validation/java5/StructuredLockingTest.java | 2 +- .../jacoco/core/test/validation/java5/SynchronizedTest.java | 2 +- .../jacoco/core/test/validation/java5/SyntheticTest.java | 2 +- .../validation/java5/targets/AnnotationGeneratedTarget.java | 2 +- .../java5/targets/AnnotationInitializerTarget.java | 2 +- .../core/test/validation/java5/targets/AssertTarget.java | 2 +- .../test/validation/java5/targets/BadCycleClassTarget.java | 2 +- .../validation/java5/targets/BooleanExpressionsTarget.java | 2 +- .../validation/java5/targets/ClassInitializerTarget.java | 2 +- .../test/validation/java5/targets/ConstructorsTarget.java | 2 +- .../ControlStructureBeforeSuperConstructorTarget.java | 2 +- .../validation/java5/targets/ControlStructuresTarget.java | 2 +- .../validation/java5/targets/EnumConstructorTarget.java | 2 +- .../validation/java5/targets/EnumImplicitMethodsTarget.java | 2 +- .../test/validation/java5/targets/EnumSwitchTarget.java | 2 +- .../test/validation/java5/targets/ExceptionsTarget.java | 2 +- .../java5/targets/ExplicitInitialFrameTarget.java | 2 +- .../targets/FieldInitializationInTwoConstructorsTarget.java | 2 +- .../core/test/validation/java5/targets/FinallyTarget.java | 2 +- .../java5/targets/ImplicitFieldInitializationTarget.java | 2 +- .../java5/targets/InterfaceClassInitializerTarget.java | 2 +- .../validation/java5/targets/StructuredLockingTarget.java | 2 +- .../test/validation/java5/targets/SynchronizedTarget.java | 2 +- .../core/test/validation/java5/targets/SyntheticTarget.java | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- .../jacoco/core/test/validation/java7/StringSwitchTest.java | 2 +- .../core/test/validation/java7/TryWithResourcesTest.java | 2 +- .../test/validation/java7/targets/StringSwitchTarget.java | 2 +- .../validation/java7/targets/TryWithResourcesTarget.java | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- .../validation/java8/AnnotationOnLocalVariableTest.java | 2 +- .../core/test/validation/java8/BadCycleInterfaceTest.java | 2 +- .../test/validation/java8/BootstrapMethodReferenceTest.java | 2 +- .../test/validation/java8/InterfaceDefaultMethodsTest.java | 2 +- .../validation/java8/InterfaceOnlyDefaultMethodsTest.java | 2 +- .../core/test/validation/java8/LambdaExpressionsTest.java | 2 +- .../core/test/validation/java8/LambdaInInterfaceTest.java | 2 +- .../java8/targets/AnnotationOnLocalVariableTarget.java | 2 +- .../validation/java8/targets/BadCycleInterfaceTarget.java | 2 +- .../java8/targets/InterfaceDefaultMethodsTarget.java | 2 +- .../java8/targets/InterfaceOnlyDefaultMethodsTarget.java | 2 +- .../validation/java8/targets/LambdaExpressionsTarget.java | 2 +- .../validation/java8/targets/LambdaInInterfaceTarget.java | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- .../test/validation/kotlin/KotlinCallableReferenceTest.java | 2 +- .../test/validation/kotlin/KotlinControlStructuresTest.java | 2 +- .../core/test/validation/kotlin/KotlinCoroutineTest.java | 2 +- .../core/test/validation/kotlin/KotlinDataClassTest.java | 2 +- .../test/validation/kotlin/KotlinDefaultArgumentsTest.java | 2 +- .../test/validation/kotlin/KotlinDefaultMethodsTest.java | 2 +- .../core/test/validation/kotlin/KotlinDelegatesTest.java | 2 +- .../test/validation/kotlin/KotlinElvisOperatorTest.java | 2 +- .../core/test/validation/kotlin/KotlinInlineTest.java | 2 +- .../test/validation/kotlin/KotlinLambdaExpressionsTest.java | 2 +- .../core/test/validation/kotlin/KotlinLateinitTest.java | 2 +- .../test/validation/kotlin/KotlinNotNullOperatorTest.java | 2 +- .../test/validation/kotlin/KotlinSafeCallOperatorTest.java | 2 +- .../core/test/validation/kotlin/KotlinSafeCastTest.java | 2 +- .../test/validation/kotlin/KotlinTopLevelFunctionTest.java | 2 +- .../validation/kotlin/KotlinUnsafeCastOperatorTest.java | 2 +- .../test/validation/kotlin/KotlinWhenExpressionTest.java | 2 +- .../kotlin/targets/KotlinCallableReferenceTarget.kt | 2 +- .../kotlin/targets/KotlinControlStructuresTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinCoroutineTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinDataClassTarget.kt | 2 +- .../kotlin/targets/KotlinDefaultArgumentsTarget.kt | 2 +- .../validation/kotlin/targets/KotlinDefaultMethodsTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinDelegatesTarget.kt | 2 +- .../validation/kotlin/targets/KotlinElvisOperatorTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinInlineTarget.kt | 2 +- .../kotlin/targets/KotlinLambdaExpressionsTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinLateinitTarget.kt | 2 +- .../kotlin/targets/KotlinNotNullOperatorTarget.kt | 2 +- .../kotlin/targets/KotlinSafeCallOperatorTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinSafeCastTarget.kt | 2 +- .../kotlin/targets/KotlinTopLevelFunctionTarget.kt | 2 +- .../kotlin/targets/KotlinUnsafeCastOperatorTarget.kt | 2 +- .../validation/kotlin/targets/KotlinWhenExpressionTarget.kt | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- .../test/validation/scala/ScalaAnonymousFunctionTest.java | 2 +- .../test/validation/scala/ScalaSingletonObjectTest.java | 2 +- .../core/test/validation/scala/ScalaSynchronizedTest.java | 2 +- .../scala/targets/ScalaAnonymousFunctionTarget.scala | 2 +- .../scala/targets/ScalaSingletonObjectTarget.scala | 2 +- .../validation/scala/targets/ScalaSynchronizedTarget.scala | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java | 2 +- .../src/org/jacoco/core/analysis/AnalyzerTest.java | 2 +- .../src/org/jacoco/core/analysis/CounterComparatorTest.java | 2 +- .../src/org/jacoco/core/analysis/CoverageBuilderTest.java | 2 +- .../src/org/jacoco/core/analysis/CoverageNodeImplTest.java | 2 +- .../src/org/jacoco/core/analysis/NodeComparatorTest.java | 2 +- .../org/jacoco/core/data/ExecutionDataReaderWriterTest.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataStoreTest.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataTest.java | 2 +- .../core/data/IncompatibleExecDataVersionExceptionTest.java | 2 +- .../src/org/jacoco/core/data/SessionInfoStoreTest.java | 2 +- .../src/org/jacoco/core/data/SessionInfoTest.java | 2 +- .../src/org/jacoco/core/instr/ClassFileVersionsTest.java | 2 +- .../src/org/jacoco/core/instr/InstrumenterTest.java | 2 +- .../src/org/jacoco/core/instr/MethodRecorder.java | 2 +- .../src/org/jacoco/core/instr/ResizeInstructionsTest.java | 2 +- .../org/jacoco/core/internal/ContentTypeDetectorTest.java | 2 +- .../src/org/jacoco/core/internal/Pack200StreamsTest.java | 2 +- .../core/internal/analysis/BundleCoverageImplTest.java | 2 +- .../jacoco/core/internal/analysis/ClassAnalyzerTest.java | 2 +- .../core/internal/analysis/ClassCoverageImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/CounterImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/InstructionTest.java | 2 +- .../core/internal/analysis/InstructionsBuilderTest.java | 2 +- .../src/org/jacoco/core/internal/analysis/LineImplTest.java | 2 +- .../jacoco/core/internal/analysis/MethodAnalyzerTest.java | 2 +- .../internal/analysis/MethodCoverageCalculatorTest.java | 2 +- .../core/internal/analysis/MethodCoverageImplTest.java | 2 +- .../jacoco/core/internal/analysis/PackageCoverageTest.java | 2 +- .../core/internal/analysis/SourceFileCoverageImplTest.java | 2 +- .../jacoco/core/internal/analysis/SourceNodeImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/StringPoolTest.java | 2 +- .../core/internal/analysis/filter/AbstractMatcherTest.java | 2 +- .../analysis/filter/AnnotationGeneratedFilterTest.java | 2 +- .../core/internal/analysis/filter/AssertFilterTest.java | 2 +- .../core/internal/analysis/filter/BridgeFilterTest.java | 2 +- .../analysis/filter/EnumEmptyConstructorFilterTest.java | 2 +- .../core/internal/analysis/filter/EnumFilterTest.java | 2 +- .../analysis/filter/ExhaustiveSwitchFilterTest.java | 2 +- .../core/internal/analysis/filter/FilterContextMock.java | 2 +- .../core/internal/analysis/filter/FilterTestBase.java | 2 +- .../core/internal/analysis/filter/FinallyFilterTest.java | 2 +- .../internal/analysis/filter/KotlinCoroutineFilterTest.java | 2 +- .../analysis/filter/KotlinDefaultArgumentsFilterTest.java | 2 +- .../analysis/filter/KotlinDefaultMethodsFilterTest.java | 2 +- .../internal/analysis/filter/KotlinGeneratedFilterTest.java | 2 +- .../internal/analysis/filter/KotlinInlineFilterTest.java | 2 +- .../internal/analysis/filter/KotlinLateinitFilterTest.java | 2 +- .../analysis/filter/KotlinNotNullOperatorFilterTest.java | 2 +- .../analysis/filter/KotlinUnsafeCastOperatorFilterTest.java | 2 +- .../core/internal/analysis/filter/KotlinWhenFilterTest.java | 2 +- .../analysis/filter/KotlinWhenStringFilterTest.java | 2 +- .../filter/PrivateEmptyNoArgConstructorFilterTest.java | 2 +- .../internal/analysis/filter/RecordPatternFilterTest.java | 2 +- .../core/internal/analysis/filter/RecordsFilterTest.java | 2 +- .../internal/analysis/filter/StringSwitchFilterTest.java | 2 +- .../analysis/filter/StringSwitchJavacFilterTest.java | 2 +- .../internal/analysis/filter/SynchronizedFilterTest.java | 2 +- .../core/internal/analysis/filter/SyntheticFilterTest.java | 2 +- .../analysis/filter/TryWithResourcesEcjFilterTest.java | 2 +- .../analysis/filter/TryWithResourcesJavac11FilterTest.java | 2 +- .../analysis/filter/TryWithResourcesJavacFilterTest.java | 2 +- .../src/org/jacoco/core/internal/data/CRC64Test.java | 2 +- .../core/internal/data/CompactDataInputOutputTest.java | 2 +- .../jacoco/core/internal/flow/ClassProbesAdapterTest.java | 2 +- .../org/jacoco/core/internal/flow/FrameSnapshotTest.java | 2 +- .../jacoco/core/internal/flow/LabelFlowAnalyzerTest.java | 2 +- .../src/org/jacoco/core/internal/flow/LabelInfoTest.java | 2 +- .../jacoco/core/internal/flow/MethodProbesAdapterTest.java | 2 +- .../org/jacoco/core/internal/flow/MethodSanitizerTest.java | 2 +- .../jacoco/core/internal/instr/ClassInstrumenterTest.java | 2 +- .../core/internal/instr/CondyProbeArrayStrategyTest.java | 2 +- .../core/internal/instr/DuplicateFrameEliminatorTest.java | 2 +- .../org/jacoco/core/internal/instr/InstrSupportTest.java | 2 +- .../jacoco/core/internal/instr/MethodInstrumenterTest.java | 2 +- .../core/internal/instr/NoneProbeArrayStrategyTest.java | 2 +- .../core/internal/instr/ProbeArrayStrategyFactoryTest.java | 2 +- .../org/jacoco/core/internal/instr/ProbeCounterTest.java | 2 +- .../org/jacoco/core/internal/instr/ProbeInserterTest.java | 2 +- .../src/org/jacoco/core/internal/instr/SafetySlotTest.java | 2 +- .../jacoco/core/internal/instr/SignatureRemoverTest.java | 2 +- .../org/jacoco/core/internal/instr/ZeroLineNumberTest.java | 2 +- .../src/org/jacoco/core/runtime/AgentOptionsTest.java | 2 +- .../src/org/jacoco/core/runtime/CommandLineSupportTest.java | 2 +- .../org/jacoco/core/runtime/InjectedClassRuntimeTest.java | 2 +- .../src/org/jacoco/core/runtime/LoggerRuntimeTest.java | 2 +- .../jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java | 2 +- .../runtime/OfflineInstrumentationAccessGeneratorTest.java | 2 +- .../jacoco/core/runtime/RemoteControlReaderWriterTest.java | 2 +- .../src/org/jacoco/core/runtime/RuntimeDataTest.java | 2 +- .../src/org/jacoco/core/runtime/RuntimeTestBase.java | 2 +- .../jacoco/core/runtime/SystemPropertiesRuntimeTest.java | 2 +- .../src/org/jacoco/core/runtime/TestStorage.java | 2 +- .../src/org/jacoco/core/runtime/WildcardMatcherTest.java | 2 +- .../src/org/jacoco/core/test/InstrumentingLoader.java | 2 +- .../src/org/jacoco/core/test/InstrumentingLoaderTest.java | 2 +- .../src/org/jacoco/core/test/TargetLoader.java | 2 +- .../src/org/jacoco/core/test/perf/AnalysisTimeScenario.java | 2 +- .../core/test/perf/ExecuteInstrumentedCodeScenario.java | 2 +- .../src/org/jacoco/core/test/perf/IPerfOutput.java | 2 +- .../src/org/jacoco/core/test/perf/IPerfScenario.java | 2 +- .../jacoco/core/test/perf/InstrumentationSizeSzenario.java | 2 +- .../jacoco/core/test/perf/InstrumentationTimeScenario.java | 2 +- .../src/org/jacoco/core/test/perf/PerfOutputWriter.java | 2 +- .../src/org/jacoco/core/test/perf/PerformanceSuite.java | 2 +- .../src/org/jacoco/core/test/perf/TimedScenario.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target01.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target02.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target03.java | 2 +- .../src/org/jacoco/core/test/validation/Compiler.java | 2 +- .../src/org/jacoco/core/test/validation/JavaVersion.java | 2 +- .../org/jacoco/core/test/validation/JavaVersionTest.java | 2 +- .../src/org/jacoco/core/test/validation/Source.java | 2 +- .../src/org/jacoco/core/test/validation/SourceTest.java | 2 +- .../org/jacoco/core/test/validation/StatementExecutor.java | 2 +- .../jacoco/core/test/validation/StatementExecutorTest.java | 2 +- .../org/jacoco/core/test/validation/StatementParser.java | 2 +- .../jacoco/core/test/validation/StatementParserTest.java | 2 +- .../org/jacoco/core/test/validation/ValidationTestBase.java | 2 +- .../src/org/jacoco/core/test/validation/targets/Stubs.java | 2 +- .../src/org/jacoco/core/tools/ExecDumpClientTest.java | 2 +- .../src/org/jacoco/core/tools/ExecFileLoaderTest.java | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.core/src/org/jacoco/core/JaCoCo.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java | 2 +- .../src/org/jacoco/core/analysis/CounterComparator.java | 2 +- .../src/org/jacoco/core/analysis/CoverageBuilder.java | 2 +- .../src/org/jacoco/core/analysis/CoverageNodeImpl.java | 2 +- .../src/org/jacoco/core/analysis/IBundleCoverage.java | 2 +- .../src/org/jacoco/core/analysis/IClassCoverage.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java | 2 +- .../src/org/jacoco/core/analysis/ICoverageNode.java | 2 +- .../src/org/jacoco/core/analysis/ICoverageVisitor.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/ILine.java | 2 +- .../src/org/jacoco/core/analysis/IMethodCoverage.java | 2 +- .../src/org/jacoco/core/analysis/IPackageCoverage.java | 2 +- .../src/org/jacoco/core/analysis/ISourceFileCoverage.java | 2 +- .../src/org/jacoco/core/analysis/ISourceNode.java | 2 +- .../src/org/jacoco/core/analysis/NodeComparator.java | 2 +- .../src/org/jacoco/core/analysis/package-info.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataReader.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataStore.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataWriter.java | 2 +- .../src/org/jacoco/core/data/IExecutionDataVisitor.java | 2 +- .../src/org/jacoco/core/data/ISessionInfoVisitor.java | 2 +- .../core/data/IncompatibleExecDataVersionException.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java | 2 +- .../src/org/jacoco/core/data/SessionInfoStore.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/package-info.java | 2 +- org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java | 2 +- org.jacoco.core/src/org/jacoco/core/instr/package-info.java | 2 +- .../src/org/jacoco/core/internal/ContentTypeDetector.java | 2 +- .../src/org/jacoco/core/internal/InputStreams.java | 2 +- .../src/org/jacoco/core/internal/Pack200Streams.java | 2 +- .../jacoco/core/internal/analysis/BundleCoverageImpl.java | 2 +- .../org/jacoco/core/internal/analysis/ClassAnalyzer.java | 2 +- .../jacoco/core/internal/analysis/ClassCoverageImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/CounterImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/Instruction.java | 2 +- .../jacoco/core/internal/analysis/InstructionsBuilder.java | 2 +- .../src/org/jacoco/core/internal/analysis/LineImpl.java | 2 +- .../org/jacoco/core/internal/analysis/MethodAnalyzer.java | 2 +- .../core/internal/analysis/MethodCoverageCalculator.java | 2 +- .../jacoco/core/internal/analysis/MethodCoverageImpl.java | 2 +- .../jacoco/core/internal/analysis/PackageCoverageImpl.java | 2 +- .../core/internal/analysis/SourceFileCoverageImpl.java | 2 +- .../org/jacoco/core/internal/analysis/SourceNodeImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/StringPool.java | 2 +- .../core/internal/analysis/filter/AbstractMatcher.java | 2 +- .../internal/analysis/filter/AnnotationGeneratedFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/AssertFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/BridgeFilter.java | 2 +- .../analysis/filter/EnumEmptyConstructorFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/EnumFilter.java | 2 +- .../internal/analysis/filter/ExhaustiveSwitchFilter.java | 2 +- .../org/jacoco/core/internal/analysis/filter/Filters.java | 2 +- .../jacoco/core/internal/analysis/filter/FinallyFilter.java | 2 +- .../org/jacoco/core/internal/analysis/filter/IFilter.java | 2 +- .../core/internal/analysis/filter/IFilterContext.java | 2 +- .../jacoco/core/internal/analysis/filter/IFilterOutput.java | 2 +- .../internal/analysis/filter/KotlinCoroutineFilter.java | 2 +- .../analysis/filter/KotlinDefaultArgumentsFilter.java | 2 +- .../analysis/filter/KotlinDefaultMethodsFilter.java | 2 +- .../internal/analysis/filter/KotlinGeneratedFilter.java | 2 +- .../core/internal/analysis/filter/KotlinInlineFilter.java | 2 +- .../core/internal/analysis/filter/KotlinLateinitFilter.java | 2 +- .../analysis/filter/KotlinNotNullOperatorFilter.java | 2 +- .../analysis/filter/KotlinUnsafeCastOperatorFilter.java | 2 +- .../core/internal/analysis/filter/KotlinWhenFilter.java | 2 +- .../internal/analysis/filter/KotlinWhenStringFilter.java | 2 +- .../analysis/filter/PrivateEmptyNoArgConstructorFilter.java | 2 +- .../core/internal/analysis/filter/RecordPatternFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/RecordsFilter.java | 2 +- .../core/internal/analysis/filter/StringSwitchFilter.java | 2 +- .../internal/analysis/filter/StringSwitchJavacFilter.java | 2 +- .../core/internal/analysis/filter/SynchronizedFilter.java | 2 +- .../core/internal/analysis/filter/SyntheticFilter.java | 2 +- .../internal/analysis/filter/TryWithResourcesEcjFilter.java | 2 +- .../analysis/filter/TryWithResourcesJavac11Filter.java | 2 +- .../analysis/filter/TryWithResourcesJavacFilter.java | 2 +- .../src/org/jacoco/core/internal/data/CRC64.java | 2 +- .../src/org/jacoco/core/internal/data/CompactDataInput.java | 2 +- .../org/jacoco/core/internal/data/CompactDataOutput.java | 2 +- .../org/jacoco/core/internal/flow/ClassProbesAdapter.java | 2 +- .../org/jacoco/core/internal/flow/ClassProbesVisitor.java | 2 +- .../src/org/jacoco/core/internal/flow/FrameSnapshot.java | 2 +- .../src/org/jacoco/core/internal/flow/IFrame.java | 2 +- .../org/jacoco/core/internal/flow/IProbeIdGenerator.java | 2 +- .../org/jacoco/core/internal/flow/LabelFlowAnalyzer.java | 2 +- .../src/org/jacoco/core/internal/flow/LabelInfo.java | 2 +- .../org/jacoco/core/internal/flow/MethodProbesAdapter.java | 2 +- .../org/jacoco/core/internal/flow/MethodProbesVisitor.java | 2 +- .../src/org/jacoco/core/internal/flow/MethodSanitizer.java | 2 +- .../core/internal/instr/ClassFieldProbeArrayStrategy.java | 2 +- .../org/jacoco/core/internal/instr/ClassInstrumenter.java | 2 +- .../jacoco/core/internal/instr/CondyProbeArrayStrategy.java | 2 +- .../core/internal/instr/DuplicateFrameEliminator.java | 2 +- .../org/jacoco/core/internal/instr/IProbeArrayStrategy.java | 2 +- .../src/org/jacoco/core/internal/instr/IProbeInserter.java | 2 +- .../src/org/jacoco/core/internal/instr/InstrSupport.java | 2 +- .../internal/instr/InterfaceFieldProbeArrayStrategy.java | 2 +- .../jacoco/core/internal/instr/LocalProbeArrayStrategy.java | 2 +- .../org/jacoco/core/internal/instr/MethodInstrumenter.java | 2 +- .../jacoco/core/internal/instr/NoneProbeArrayStrategy.java | 2 +- .../core/internal/instr/ProbeArrayStrategyFactory.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeCounter.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeInserter.java | 2 +- .../org/jacoco/core/internal/instr/SignatureRemover.java | 2 +- org.jacoco.core/src/org/jacoco/core/package-info.java | 2 +- .../src/org/jacoco/core/runtime/AbstractRuntime.java | 2 +- .../src/org/jacoco/core/runtime/AgentOptions.java | 2 +- .../src/org/jacoco/core/runtime/CommandLineSupport.java | 2 +- .../core/runtime/IExecutionDataAccessorGenerator.java | 2 +- .../src/org/jacoco/core/runtime/IRemoteCommandVisitor.java | 2 +- org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java | 2 +- .../src/org/jacoco/core/runtime/InjectedClassRuntime.java | 2 +- .../src/org/jacoco/core/runtime/LoggerRuntime.java | 2 +- .../org/jacoco/core/runtime/ModifiedSystemClassRuntime.java | 2 +- .../core/runtime/OfflineInstrumentationAccessGenerator.java | 2 +- .../src/org/jacoco/core/runtime/RemoteControlReader.java | 2 +- .../src/org/jacoco/core/runtime/RemoteControlWriter.java | 2 +- .../src/org/jacoco/core/runtime/RuntimeData.java | 2 +- .../org/jacoco/core/runtime/SystemPropertiesRuntime.java | 2 +- .../src/org/jacoco/core/runtime/WildcardMatcher.java | 2 +- .../src/org/jacoco/core/runtime/package-info.java | 2 +- .../src/org/jacoco/core/tools/ExecDumpClient.java | 2 +- .../src/org/jacoco/core/tools/ExecFileLoader.java | 2 +- org.jacoco.core/src/org/jacoco/core/tools/package-info.java | 2 +- org.jacoco.doc/pom.xml | 2 +- org.jacoco.doc/xsl/cli.xsl | 2 +- org.jacoco.doc/xsl/maven-goal.xsl | 2 +- org.jacoco.examples.test/pom.xml | 2 +- .../src/org/jacoco/examples/ClassInfoTest.java | 2 +- .../src/org/jacoco/examples/ConsoleOutput.java | 2 +- .../src/org/jacoco/examples/CoreTutorialTest.java | 2 +- .../src/org/jacoco/examples/ExecDumpTest.java | 2 +- .../src/org/jacoco/examples/MBeanClientTest.java | 2 +- org.jacoco.examples.test/src/test/resources/verify-it.bsh | 2 +- .../src/test/resources/verify-offline.bsh | 2 +- org.jacoco.examples.test/src/test/resources/verify.bsh | 2 +- org.jacoco.examples/assembly.xml | 2 +- org.jacoco.examples/build/build-offline.xml | 2 +- org.jacoco.examples/build/build.xml | 2 +- org.jacoco.examples/build/pom-it.xml | 2 +- org.jacoco.examples/build/pom-offline.xml | 2 +- org.jacoco.examples/build/pom.xml | 2 +- .../src/main/java/org/jacoco/examples/expressions/Add.java | 2 +- .../main/java/org/jacoco/examples/expressions/Const.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Div.java | 2 +- .../java/org/jacoco/examples/expressions/IExpression.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Mul.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Sub.java | 2 +- .../java/org/jacoco/examples/parser/ExpressionParser.java | 2 +- .../src/main/java/org/jacoco/examples/parser/Main.java | 2 +- .../java/org/jacoco/examples/parser/ExpressionParserIT.java | 2 +- .../org/jacoco/examples/parser/ExpressionParserTest.java | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java | 2 +- .../src/org/jacoco/examples/CoreTutorial.java | 2 +- org.jacoco.examples/src/org/jacoco/examples/ExecDump.java | 2 +- .../src/org/jacoco/examples/ExecutionDataClient.java | 2 +- .../src/org/jacoco/examples/ExecutionDataServer.java | 2 +- .../src/org/jacoco/examples/MBeanClient.java | 2 +- .../src/org/jacoco/examples/ReportGenerator.java | 2 +- org.jacoco.report.test/pom.xml | 2 +- .../org/jacoco/report/DirectorySourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/FileMultiReportOutputTest.java | 2 +- .../org/jacoco/report/InputStreamSourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/JavaNamesTest.java | 2 +- .../src/org/jacoco/report/MemoryMultiReportOutput.java | 2 +- .../src/org/jacoco/report/MemoryOutput.java | 2 +- .../src/org/jacoco/report/MultiReportVisitorTest.java | 2 +- .../src/org/jacoco/report/MultiSourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/ReportStructureTestDriver.java | 2 +- .../src/org/jacoco/report/ZipMultiReportOutputTest.java | 2 +- .../src/org/jacoco/report/check/BundleCheckerTest.java | 2 +- .../src/org/jacoco/report/check/LimitTest.java | 2 +- .../src/org/jacoco/report/check/RuleTest.java | 2 +- .../src/org/jacoco/report/check/RulesCheckerTest.java | 2 +- .../src/org/jacoco/report/csv/CSVFormatterTest.java | 2 +- .../src/org/jacoco/report/csv/CSVGroupHandlerTest.java | 2 +- .../src/org/jacoco/report/csv/ClassRowWriterTest.java | 2 +- .../src/org/jacoco/report/csv/DelimitedWriterTest.java | 2 +- .../src/org/jacoco/report/html/HTMLFormatterTest.java | 2 +- .../org/jacoco/report/internal/NormalizedFileNamesTest.java | 2 +- .../org/jacoco/report/internal/ReportOutputFolderTest.java | 2 +- .../org/jacoco/report/internal/html/HTMLElementTest.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLSupport.java | 2 +- .../src/org/jacoco/report/internal/html/LinkableStub.java | 2 +- .../jacoco/report/internal/html/page/BundlePageTest.java | 2 +- .../org/jacoco/report/internal/html/page/ClassPageTest.java | 2 +- .../jacoco/report/internal/html/page/MethodItemTest.java | 2 +- .../org/jacoco/report/internal/html/page/NodePageTest.java | 2 +- .../jacoco/report/internal/html/page/PackagePageTest.java | 2 +- .../report/internal/html/page/PackageSourcePageTest.java | 2 +- .../org/jacoco/report/internal/html/page/PageTestBase.java | 2 +- .../jacoco/report/internal/html/page/ReportPageTest.java | 2 +- .../jacoco/report/internal/html/page/SessionsPageTest.java | 2 +- .../report/internal/html/page/SourceFilePageTest.java | 2 +- .../report/internal/html/page/SourceHighlighterTest.java | 2 +- .../report/internal/html/resources/ResourcesTest.java | 2 +- .../jacoco/report/internal/html/resources/StylesTest.java | 2 +- .../jacoco/report/internal/html/table/BarColumnTest.java | 2 +- .../report/internal/html/table/CounterColumnTest.java | 2 +- .../jacoco/report/internal/html/table/LabelColumnTest.java | 2 +- .../report/internal/html/table/PercentageColumnTest.java | 2 +- .../jacoco/report/internal/html/table/SortIndexTest.java | 2 +- .../org/jacoco/report/internal/html/table/TableTest.java | 2 +- .../org/jacoco/report/internal/xml/LocalEntityResolver.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLElementTest.java | 2 +- .../org/jacoco/report/internal/xml/XMLGroupVisitorTest.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLSupport.java | 2 +- .../src/org/jacoco/report/xml/XMLFormatterTest.java | 2 +- org.jacoco.report/pom.xml | 2 +- .../src/org/jacoco/report/DirectorySourceFileLocator.java | 2 +- .../src/org/jacoco/report/FileMultiReportOutput.java | 2 +- org.jacoco.report/src/org/jacoco/report/ILanguageNames.java | 2 +- .../src/org/jacoco/report/IMultiReportOutput.java | 2 +- .../src/org/jacoco/report/IReportGroupVisitor.java | 2 +- org.jacoco.report/src/org/jacoco/report/IReportVisitor.java | 2 +- .../src/org/jacoco/report/ISourceFileLocator.java | 2 +- .../src/org/jacoco/report/InputStreamSourceFileLocator.java | 2 +- org.jacoco.report/src/org/jacoco/report/JavaNames.java | 2 +- .../src/org/jacoco/report/MultiReportVisitor.java | 2 +- .../src/org/jacoco/report/MultiSourceFileLocator.java | 2 +- .../src/org/jacoco/report/ZipMultiReportOutput.java | 2 +- .../src/org/jacoco/report/check/BundleChecker.java | 2 +- .../src/org/jacoco/report/check/IViolationsOutput.java | 2 +- org.jacoco.report/src/org/jacoco/report/check/Limit.java | 2 +- org.jacoco.report/src/org/jacoco/report/check/Rule.java | 2 +- .../src/org/jacoco/report/check/RulesChecker.java | 2 +- .../src/org/jacoco/report/check/package-info.java | 2 +- .../src/org/jacoco/report/csv/CSVFormatter.java | 2 +- .../src/org/jacoco/report/csv/CSVGroupHandler.java | 2 +- .../src/org/jacoco/report/csv/ClassRowWriter.java | 2 +- .../src/org/jacoco/report/csv/DelimitedWriter.java | 2 +- .../src/org/jacoco/report/csv/package-info.java | 2 +- .../src/org/jacoco/report/html/HTMLFormatter.java | 2 +- .../src/org/jacoco/report/html/package-info.java | 2 +- .../org/jacoco/report/internal/AbstractGroupVisitor.java | 2 +- .../src/org/jacoco/report/internal/NormalizedFileNames.java | 2 +- .../src/org/jacoco/report/internal/ReportOutputFolder.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLElement.java | 2 +- .../org/jacoco/report/internal/html/HTMLGroupVisitor.java | 2 +- .../org/jacoco/report/internal/html/IHTMLReportContext.java | 2 +- .../src/org/jacoco/report/internal/html/ILinkable.java | 2 +- .../org/jacoco/report/internal/html/index/ElementIndex.java | 2 +- .../org/jacoco/report/internal/html/index/IIndexUpdate.java | 2 +- .../org/jacoco/report/internal/html/index/package-info.java | 2 +- .../org/jacoco/report/internal/html/page/BundlePage.java | 2 +- .../src/org/jacoco/report/internal/html/page/ClassPage.java | 2 +- .../src/org/jacoco/report/internal/html/page/GroupPage.java | 2 +- .../org/jacoco/report/internal/html/page/MethodItem.java | 2 +- .../src/org/jacoco/report/internal/html/page/NodePage.java | 2 +- .../org/jacoco/report/internal/html/page/PackagePage.java | 2 +- .../jacoco/report/internal/html/page/PackageSourcePage.java | 2 +- .../org/jacoco/report/internal/html/page/ReportPage.java | 2 +- .../org/jacoco/report/internal/html/page/SessionsPage.java | 2 +- .../jacoco/report/internal/html/page/SourceFileItem.java | 2 +- .../jacoco/report/internal/html/page/SourceFilePage.java | 2 +- .../jacoco/report/internal/html/page/SourceHighlighter.java | 2 +- .../src/org/jacoco/report/internal/html/page/TablePage.java | 2 +- .../jacoco/report/internal/html/resources/Resources.java | 2 +- .../org/jacoco/report/internal/html/resources/Styles.java | 2 +- .../jacoco/report/internal/html/resources/package-info.java | 2 +- .../src/org/jacoco/report/internal/html/resources/sort.js | 2 +- .../org/jacoco/report/internal/html/table/BarColumn.java | 2 +- .../jacoco/report/internal/html/table/CounterColumn.java | 2 +- .../jacoco/report/internal/html/table/IColumnRenderer.java | 2 +- .../org/jacoco/report/internal/html/table/ITableItem.java | 2 +- .../org/jacoco/report/internal/html/table/LabelColumn.java | 2 +- .../jacoco/report/internal/html/table/PercentageColumn.java | 2 +- .../org/jacoco/report/internal/html/table/SortIndex.java | 2 +- .../src/org/jacoco/report/internal/html/table/Table.java | 2 +- .../report/internal/html/table/TableItemComparator.java | 2 +- .../org/jacoco/report/internal/html/table/package-info.java | 2 +- .../src/org/jacoco/report/internal/xml/ReportElement.java | 2 +- .../org/jacoco/report/internal/xml/XMLCoverageWriter.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLElement.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLGroupVisitor.java | 2 +- org.jacoco.report/src/org/jacoco/report/package-info.java | 2 +- .../src/org/jacoco/report/xml/XMLFormatter.java | 2 +- .../src/org/jacoco/report/xml/package-info.java | 2 +- org.jacoco.report/src/org/jacoco/report/xml/report.dtd | 2 +- org.jacoco.tests/pom.xml | 2 +- 791 files changed, 793 insertions(+), 793 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 757dbf4afb..0c2e74523f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ License ======= -Copyright (c) 2009, 2023 Mountainminds GmbH & Co. KG and Contributors +Copyright (c) 2009, 2024 Mountainminds GmbH & Co. KG and Contributors The JaCoCo Java Code Coverage Library and all included documentation is made available by Mountainminds GmbH & Co. KG, Munich. Except indicated below, the diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml index c7221a1eac..2b58a34d1d 100644 --- a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml +++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml @@ -1,6 +1,6 @@ - 9.6 + 9.7 1.9.16 2.0.28 4.13.1 diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 6e366abe17..e2a5104e10 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -38,6 +38,12 @@

    Fixed bugs

    (GitHub #1568). +

    Non-functional Changes

    +
      +
    • JaCoCo now depends on ASM 9.7 + (GitHub #1600).
    • +
    +

    Release 0.8.11 (2023/10/14)

    New Features

    From 03a53334c1e3a28ed587feb5adbfa3c0aa536990 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 25 Mar 2024 21:02:18 +0100 Subject: [PATCH 036/255] Add configuration for Dependabot to simplify updates of ASM (#1601) --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ace4600a1..500fc25530 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,9 @@ updates: directory: "/" schedule: interval: "weekly" + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + allow: + - dependency-name: "org.ow2.asm:*" From fd63cc5478bcd7b32e2070d93ead8c879b423841 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:16:31 +0100 Subject: [PATCH 037/255] Configure labels that Dependabot assigns to PRs (#1603) --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 500fc25530..51d2ae7554 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,9 +4,15 @@ updates: directory: "/" schedule: interval: "weekly" + labels: + - "dependencies" + - "component: build" - package-ecosystem: "maven" directory: "/" schedule: interval: "daily" + labels: + - "dependencies" + - "component: core" allow: - dependency-name: "org.ow2.asm:*" From a50585b9e0770c363c56d887a8f639dc05411073 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:41:52 +0100 Subject: [PATCH 038/255] Upgrade maven-plugin-plugin to 3.6.4 (#1604) --- org.jacoco.build/pom.xml | 101 ++++++++------------------------------- 1 file changed, 21 insertions(+), 80 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 98389cc93d..b4428e5db0 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -361,15 +361,7 @@ org.apache.maven.plugins maven-plugin-plugin - 3.6.0 - - - - org.ow2.asm - asm - 7.1 - - + 3.6.4 org.apache.maven.plugins @@ -794,67 +786,16 @@
    - - java14-bytecode - - - bytecode.version - 14 - - - - 13 - 13 - - - - - java15-bytecode - - - bytecode.version - 15 - - - - 13 - 13 - - - - - java16-bytecode - - - bytecode.version - 16 - - - - 13 - 13 - - - - - java17-bytecode - - - bytecode.version - 17 - - - - 13 - 13 - - - java18-bytecode @@ -864,8 +805,8 @@ - 13 - 13 + 17 + 17 @@ -878,8 +819,8 @@ - 13 - 13 + 17 + 17 @@ -892,8 +833,8 @@ - 13 - 13 + 17 + 17 @@ -906,8 +847,8 @@ - 13 - 13 + 17 + 17 @@ -920,8 +861,8 @@ - 13 - 13 + 17 + 17 @@ -934,8 +875,8 @@ - 13 - 13 + 17 + 17 From dbfb6f2ad904158b5b40a93fea222e263aeaf9ab Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sun, 31 Mar 2024 22:07:30 +0200 Subject: [PATCH 039/255] Prepare release 0.8.12 --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 +- org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index e18b84dc05..b469b2f8bb 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index b8d3097722..e40e225fac 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index 6245081498..ce63e89882 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index ff5dfb5c85..5e56469027 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index e79d76e184..91bdc54cfa 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index 0593d7ead3..233a959b29 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index 73c0a6b84e..b98e2b1ae7 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index 9ad23e59c9..72056946f1 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index fcde6604fe..40b3ea51a8 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index b4428e5db0..fef442fdc7 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index 78456d541d..28bdfc1cdd 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 9eb72d88d3..2aad3c2039 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index bf0cd00182..cfb53753cf 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index 6761ad53c2..5553e6b3b7 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index d1a1dcc0de..713c2b556c 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index a54a1b0d2c..0d02516aa7 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index 58be6f1822..67db528cb3 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index d6463a55d5..1f8965352f 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index 665c9ead5e..c060e95edc 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 631093dc6e..e7dfae9ee6 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index 1ee01be0d6..43e606550e 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 9829c49101..eae91b61d4 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index a037c11bbc..0124bf70f3 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index d17186856d..76504a1dbd 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index e2a5104e10..e3a567d5e2 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,7 +18,7 @@

    Change History

    -

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    +

    Release 0.8.12 (2024/03/31)

    New Features

      diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index 8f9a867dc7..c18ae75de6 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index e829b6e3f9..8b927e04ef 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index a8acdde10b..eee4d67011 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index 10bd88ecf4..2dcac9b32e 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index 9c1f201e28..6542442bfb 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index d62357644e..36fac96925 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.12-SNAPSHOT + 0.8.12 ../org.jacoco.build diff --git a/pom.xml b/pom.xml index 1f88a8b0dd..12c371ca79 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.12-SNAPSHOT + 0.8.12 pom From 337c80f7c01ce699b1a8eb7916f03aa74c02eaed Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sun, 31 Mar 2024 22:09:29 +0200 Subject: [PATCH 040/255] Prepare for next development iteration --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 33 insertions(+), 31 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index b469b2f8bb..ffca23e99c 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index e40e225fac..6eb088957c 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index ce63e89882..7d919d08c4 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index 5e56469027..9fbc61edd5 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index 91bdc54cfa..9a42d840b6 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index 233a959b29..42da9c26b6 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index b98e2b1ae7..89b5c15754 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index 72056946f1..0decb5008b 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index 40b3ea51a8..8809fddd1c 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index fef442fdc7..1ea398c344 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index 28bdfc1cdd..1d532934e3 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 2aad3c2039..358c2808f4 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index cfb53753cf..6732b7c5fa 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index 5553e6b3b7..8d64ec96ec 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index 713c2b556c..9e5f095a66 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index 0d02516aa7..ccef737085 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index 67db528cb3..28822239d0 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 1f8965352f..4877157585 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index c060e95edc..4a151e1155 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index e7dfae9ee6..0cebf67846 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index 43e606550e..296202b368 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index eae91b61d4..ad96138fd6 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index 0124bf70f3..45a40d90e5 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index 76504a1dbd..6857f13c43 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index e3a567d5e2..48b2ac196e 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,6 +18,8 @@

      Change History

      +

      Snapshot Build @qualified.bundle.version@ (@build.date@)

      +

      Release 0.8.12 (2024/03/31)

      New Features

      diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index c18ae75de6..6176308713 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index 8b927e04ef..45b0b9ffe6 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index eee4d67011..5dbd27cab3 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index 2dcac9b32e..40705b1e6d 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index 6542442bfb..03d0e91820 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index 36fac96925..dc6b07372c 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.12 + 0.8.13-SNAPSHOT ../org.jacoco.build diff --git a/pom.xml b/pom.xml index 12c371ca79..dc71687067 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.12 + 0.8.13-SNAPSHOT pom From 2f7f84172f4127d74b33bd333a9da60c33cc176d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:37:54 +0200 Subject: [PATCH 041/255] Fix build with JDK >= 20 when option `-Dbytecode.version` is not provided (#1605) --- org.jacoco.build/pom.xml | 29 ++++++++++++++++++- org.jacoco.core.test.validation.java7/pom.xml | 18 +++++++++--- org.jacoco.doc/docroot/doc/build.html | 6 ++-- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 1ea398c344..1a0e8448c0 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -744,13 +744,40 @@ maven-jdk12 - [12,) + [12,20) 7 + + + maven-jdk20 + + [20,) + + + 8 + + + + + + intellij + + + idea.maven.embedder.version + + + + 5 + + + integration-tests diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 4877157585..3f7d34dad9 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -24,14 +24,24 @@ JaCoCo :: Test :: Core :: Validation Java 7 - - 7 - - ${project.groupId} org.jacoco.core.test + + + + intellij + + + idea.maven.embedder.version + + + + 7 + + + diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index 8cca1348e6..46600cdd1a 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -287,9 +287,9 @@

      Compilation and testing with different JDKs

      7 7 7 - 7 - 7 - 7 + 8 + 8 + 8 From 92edc21fd80c8080d1ee141a33ef7c7e381197e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:30:23 +0200 Subject: [PATCH 042/255] Bump actions/upload-artifact from 4.3.1 to 4.3.3 (#1611) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.1 to 4.3.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/5d5d22a31266ced268874388b861e4b58bb5c2f3...65462800fd760344b1a7b4382951275a0abb4808) --- 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 980990658f..8d0f929bda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: mvn -V -B -e --no-transfer-progress \ verify -Djdk.version=6 -Dbytecode.version=5 \ --toolchains=toolchains.xml - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 id: artifact-upload-step with: name: jacoco From 230937dc3854055bac57ad600fd585a563397a26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 08:55:45 +0000 Subject: [PATCH 043/255] Bump actions/checkout from 4.1.1 to 4.1.4 (#1613) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.4. - [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/b4ffde65f46336ab88eb53be808477a3936bae11...0ad4b8fadaa221de15dcec353f45205ec38ea70b) --- 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 8d0f929bda..911151c74b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: name: JDK ${{ matrix.jdk }} runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' @@ -49,7 +49,7 @@ jobs: Windows: runs-on: windows-2022 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' From 1ad4a155973702f3714034c9b9ab29788b670c02 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 1 May 2024 07:08:09 +0200 Subject: [PATCH 044/255] Upgrade Kotlin to 1.9.23 (#1567) --- .../pom.xml | 4 +-- .../targets/KotlinWhenExpressionTarget.kt | 3 +- org.jacoco.core.test.validation/pom.xml | 34 +++++++------------ org.jacoco.doc/docroot/doc/build.html | 34 +++++++++---------- 4 files changed, 33 insertions(+), 42 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 0cebf67846..00f7845aad 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 - 1.5.0 + 1.9.23 @@ -41,7 +41,7 @@ org.jetbrains.kotlinx kotlinx-coroutines-core - 1.0.1 + 1.8.0 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 f38b10d4ae..ccf98244bb 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 @@ -63,8 +63,9 @@ object KotlinWhenExpressionTarget { /** * 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) { // assertFullyCovered(0, 6) + private fun whenStringBiggestHashCodeFirst(p: String): Int = when (p) { // assertPartlyCovered(3, 11) "c" -> 1 // assertFullyCovered() "b" -> 2 // assertFullyCovered() "\u0000b" -> 3 // assertFullyCovered() diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index ad96138fd6..c652601969 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -34,7 +34,6 @@ true - 1.6 1.8 @@ -68,10 +67,8 @@ - 1.6 - ../org.jacoco.core.test.validation.kotlin
      @@ -84,7 +81,6 @@ - ../org.jacoco.core.test.validation.kotlin @@ -97,11 +93,8 @@ - - 1.6 - ../org.jacoco.core.test.validation.kotlin ../org.jacoco.core.test.validation.java7 @@ -115,7 +108,6 @@ - ../org.jacoco.core.test.validation.kotlin ../org.jacoco.core.test.validation.java7 @@ -125,6 +117,9 @@ true + + 1.8 + ../org.jacoco.core.test.validation.kotlin ../org.jacoco.core.test.validation.java7 @@ -346,8 +341,7 @@ - - 16 + 17 17 17 @@ -373,8 +367,7 @@ - - 16 + 18 16 @@ -401,8 +394,7 @@ - - 16 + 19 16 @@ -429,8 +421,7 @@ - - 16 + 20 16 @@ -457,8 +448,7 @@ - - 16 + 21 16 @@ -486,8 +476,8 @@ - - 16 + + 21 16 @@ -517,8 +507,8 @@ - - 16 + + 21 16 diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index 46600cdd1a..06217bce87 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -231,23 +231,23 @@

      Compilation and testing with different JDKs

      org.jacoco.core.test.validation.kotlin - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 6 + + + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 org.jacoco.core.test.validation.scala From 726dcdf88ca022f1cead486cc4ca239b669c80ea Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 2 May 2024 19:55:24 +0200 Subject: [PATCH 045/255] Starting from JDK 20 compilation into bytecode version 7 not supported (#1615) --- org.jacoco.doc/docroot/doc/build.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index 06217bce87..89ed086914 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -203,9 +203,9 @@

      Compilation and testing with different JDKs

      7 7 7 - 7 - 7 - 7 + 8 + 8 + 8 org.jacoco.core.test.validation.groovy From 7ab41d16f2abefb80b6d7788bde2cc4114b38a0e Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 4 May 2024 12:16:59 +0200 Subject: [PATCH 046/255] Add filter for bytecode generated by Compose Kotlin compiler plugin (#1616) --- .../filter/KotlinComposeFilterTest.java | 255 ++++++++++++++++++ .../internal/analysis/filter/Filters.java | 3 +- .../analysis/filter/KotlinComposeFilter.java | 83 ++++++ org.jacoco.doc/docroot/doc/changes.html | 7 + 4 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.java diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java new file mode 100644 index 0000000000..a6564f15cc --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * 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 static org.objectweb.asm.Opcodes.*; + +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.MethodNode; + +/** + * Unit tests for {@link KotlinComposeFilter}. + */ +public class KotlinComposeFilterTest extends FilterTestBase { + + private final IFilter filter = new KotlinComposeFilter(); + + /** + *
      +	 * @androidx.compose.runtime.Composable
      +	 * fun example(x: Int) {
      +	 *   if (x < 0)
      +	 *     return
      +	 *   example(x - 1)
      +	 * }
      +	 * 
      + * + * transformed by Compose + * Kotlin compiler plugin version 2.0.0 into + * + *
      +	 * fun example(x: Int, $composer: Composer?, $changed: Int) {
      +	 *   $composer = $composer.startRestartGroup(...)
      +	 *   sourceInformation($composer, ...)
      +	 *   val $dirty = $changed
      +	 *   if ($changed and 0b0110 == 0) {
      +	 *     $dirty = $dirty or if ($composer.changed(x)) 0b0100 else 0b0010
      +	 *   }
      +	 *   if ($dirty and 0b0011 != 0b0010 || !$composer.skipping) {
      +	 *     if (isTraceInProgress()) {
      +	 *       traceEventStart(...)
      +	 *     }
      +	 *
      +	 *     if (x < 0) {
      +	 *       if (isTraceInProgress()) {
      +	 *         traceEventEnd()
      +	 *       }
      +	 *       $composer.endRestartGroup()?.updateScope { ... }
      +	 *       return
      +	 *     }
      +	 *
      +	 *     example(x, $composer, 0)
      +	 *
      +	 *     if (isTraceInProgress()) {
      +	 *       traceEventEnd()
      +	 *     }
      +	 *   } else {
      +	 *     $composer.skipToGroupEnd()
      +	 *   }
      +	 *   $composer.endRestartGroup()?.updateScope { ... }
      +	 * }
      +	 * 
      + */ + @Test + public void should_filter() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "f", "(Landroidx/compose/runtime/Composer;I)V", null, null); + m.visitAnnotation("Landroidx/compose/runtime/Composable;", false); + + final Range range1 = new Range(); + final Range range2 = new Range(); + final Range range3 = new Range(); + final Range range4 = new Range(); + final Range range5 = new Range(); + final Range range6 = new Range(); + final Range range7 = new Range(); + + m.visitVarInsn(ALOAD, 1); + range1.fromInclusive = m.instructions.getLast(); + m.visitLdcInsn(Integer.valueOf(-974630231)); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "startRestartGroup", "(I)Landroidx/compose/runtime/Composer;", + true); + m.visitVarInsn(ASTORE, 1); + m.visitVarInsn(ILOAD, 2); + m.visitVarInsn(ISTORE, 3); + Label label1 = new Label(); + m.visitLabel(label1); + m.visitVarInsn(ILOAD, 2); + m.visitIntInsn(BIPUSH, 14); + m.visitInsn(IAND); + Label label2 = new Label(); + m.visitJumpInsn(IFNE, label2); + m.visitVarInsn(ILOAD, 3); + m.visitVarInsn(ALOAD, 1); + m.visitVarInsn(ILOAD, 0); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "changed", "(I)Z", true); + Label label3 = new Label(); + m.visitJumpInsn(IFEQ, label3); + m.visitInsn(ICONST_4); + Label label4 = new Label(); + m.visitJumpInsn(GOTO, label4); + m.visitLabel(label3); + m.visitInsn(ICONST_2); + m.visitLabel(label4); + m.visitInsn(IOR); + m.visitVarInsn(ISTORE, 3); + m.visitLabel(label2); + m.visitVarInsn(ILOAD, 3); + m.visitIntInsn(BIPUSH, 11); + m.visitInsn(IAND); + m.visitInsn(ICONST_2); + Label label5 = new Label(); + m.visitJumpInsn(IF_ICMPNE, label5); + m.visitVarInsn(ALOAD, 1); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "getSkipping", "()Z", true); + Label label6 = new Label(); + m.visitJumpInsn(IFNE, label6); + range1.toInclusive = m.instructions.getLast(); + + m.visitLabel(label5); + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "isTraceInProgress", "()Z", false); + Label label7 = new Label(); + m.visitJumpInsn(IFEQ, label7); + range3.fromInclusive = m.instructions.getLast(); + m.visitLdcInsn(Integer.valueOf(-974630231)); + m.visitVarInsn(ILOAD, 3); + m.visitInsn(ICONST_M1); + m.visitLdcInsn("org.example.example (Example.kt:19)"); + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "traceEventStart", "(IIILjava/lang/String;)V", false); + m.visitLabel(label7); + range3.toInclusive = m.instructions.getLast(); + + m.visitVarInsn(ILOAD, 0); + Label label8 = new Label(); + m.visitJumpInsn(IFGE, label8); + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "isTraceInProgress", "()Z", false); + Label label9 = new Label(); + m.visitJumpInsn(IFEQ, label9); + range4.fromInclusive = m.instructions.getLast(); + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "traceEventEnd", "()V", false); + m.visitLabel(label9); + range4.toInclusive = m.instructions.getLast(); + + m.visitVarInsn(ALOAD, 1); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "endRestartGroup", + "()Landroidx/compose/runtime/ScopeUpdateScope;", true); + m.visitInsn(DUP); + Label label10 = new Label(); + m.visitJumpInsn(IFNULL, label10); + range5.fromInclusive = m.instructions.getLast(); + m.visitTypeInsn(NEW, "org/example/ExampleKt$example$4"); + m.visitInsn(DUP); + m.visitVarInsn(ILOAD, 0); + m.visitVarInsn(ILOAD, 2); + m.visitMethodInsn(INVOKESPECIAL, "org/example/ExampleKt$example$4", + "", "(II)V", false); + m.visitTypeInsn(CHECKCAST, "kotlin/jvm/functions/Function2"); + m.visitMethodInsn(INVOKEINTERFACE, + "androidx/compose/runtime/ScopeUpdateScope", "updateScope", + "(Lkotlin/jvm/functions/Function2;)V", true); + Label label11 = new Label(); + m.visitJumpInsn(GOTO, label11); + m.visitLabel(label10); + m.visitFrame(Opcodes.F_SAME1, 0, null, 1, + new Object[] { "androidx/compose/runtime/ScopeUpdateScope" }); + m.visitInsn(POP); + range5.toInclusive = m.instructions.getLast(); + + m.visitLabel(label11); + m.visitInsn(Opcodes.RETURN); + + m.visitLabel(label8); + m.visitVarInsn(ILOAD, 0); + m.visitInsn(ICONST_1); + m.visitInsn(ISUB); + m.visitVarInsn(ALOAD, 1); + m.visitInsn(ICONST_0); + m.visitMethodInsn(INVOKESTATIC, "org/example/ExampleKt", "example", + "(ILandroidx/compose/runtime/Composer;I)V", false); + + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "isTraceInProgress", "()Z", false); + Label label12 = new Label(); + m.visitJumpInsn(IFEQ, label12); + range6.fromInclusive = m.instructions.getLast(); + m.visitMethodInsn(INVOKESTATIC, "androidx/compose/runtime/ComposerKt", + "traceEventEnd", "()V", false); + m.visitJumpInsn(GOTO, label12); + m.visitLabel(label6); + range2.fromInclusive = m.instructions.getLast(); + m.visitVarInsn(ALOAD, 1); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "skipToGroupEnd", "()V", true); + m.visitLabel(label12); + range6.toInclusive = m.instructions.getLast(); + + m.visitVarInsn(ALOAD, 1); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "endRestartGroup", + "()Landroidx/compose/runtime/ScopeUpdateScope;", true); + m.visitInsn(DUP); + Label label13 = new Label(); + m.visitJumpInsn(IFNULL, label13); + range7.fromInclusive = m.instructions.getLast(); + m.visitTypeInsn(NEW, "org/example/ExampleKt$example$5"); + m.visitInsn(DUP); + m.visitVarInsn(ILOAD, 0); + m.visitVarInsn(ILOAD, 2); + m.visitMethodInsn(INVOKESPECIAL, "org/example/ExampleKt$example$5", + "", "(II)V", false); + m.visitTypeInsn(CHECKCAST, "kotlin/jvm/functions/Function2"); + m.visitMethodInsn(INVOKEINTERFACE, + "androidx/compose/runtime/ScopeUpdateScope", "updateScope", + "(Lkotlin/jvm/functions/Function2;)V", true); + Label label14 = new Label(); + m.visitJumpInsn(GOTO, label14); + m.visitLabel(label13); + m.visitFrame(Opcodes.F_SAME1, 0, null, 1, + new Object[] { "androidx/compose/runtime/ScopeUpdateScope" }); + m.visitInsn(POP); + range7.toInclusive = m.instructions.getLast(); + + m.visitLabel(label14); + m.visitInsn(RETURN); + range2.toInclusive = m.instructions.getLast(); + + filter.filter(m, context, output); + + assertIgnored(range1, range2, range3, range4, range5, range6, range7); + } + +} 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 70bb751ec0..07268c4121 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 @@ -48,7 +48,8 @@ public static IFilter all() { new KotlinUnsafeCastOperatorFilter(), new KotlinNotNullOperatorFilter(), new KotlinDefaultArgumentsFilter(), new KotlinInlineFilter(), - new KotlinCoroutineFilter(), new KotlinDefaultMethodsFilter()); + new KotlinCoroutineFilter(), new KotlinDefaultMethodsFilter(), + new KotlinComposeFilter()); } private Filters(final IFilter... filters) { 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 new file mode 100644 index 0000000000..48a1fbd565 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilter.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 org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters bytecode generated by Compose Kotlin compiler plugin. + */ +final class KotlinComposeFilter implements IFilter { + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + if (!KotlinGeneratedFilter.isKotlinClass(context)) { + return; + } + if (!isComposable(methodNode)) { + return; + } + for (final AbstractInsnNode i : methodNode.instructions) { + if (i.getType() != AbstractInsnNode.METHOD_INSN) { + continue; + } + final MethodInsnNode mi = (MethodInsnNode) i; + if ("androidx/compose/runtime/Composer".equals(mi.owner) + && "getSkipping".equals(mi.name) && "()Z".equals(mi.desc) + && mi.getNext().getOpcode() == Opcodes.IFNE) { + // https://github.com/JetBrains/kotlin/blob/v2.0.0-RC2/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt#L361-L384 + final JumpInsnNode ji = (JumpInsnNode) mi.getNext(); + output.ignore(methodNode.instructions.getFirst(), ji); + output.ignore(ji.label, methodNode.instructions.getLast()); + } else if ("androidx/compose/runtime/Composer".equals(mi.owner) + && "endRestartGroup".equals(mi.name) + && "()Landroidx/compose/runtime/ScopeUpdateScope;" + .equals(mi.desc) + && mi.getNext().getOpcode() == Opcodes.DUP + && mi.getNext().getNext().getOpcode() == Opcodes.IFNULL) { + // https://github.com/JetBrains/kotlin/blob/v2.0.0-RC2/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt#L430-L450 + final JumpInsnNode ji = (JumpInsnNode) mi.getNext().getNext(); + final AbstractInsnNode jumpTarget = AbstractMatcher + .skipNonOpcodes(ji.label); + if (jumpTarget.getOpcode() == Opcodes.POP) { + output.ignore(ji, jumpTarget); + } + } else if ("androidx/compose/runtime/ComposerKt".equals(mi.owner) + && "isTraceInProgress".equals(mi.name) + && "()Z".equals(mi.desc) + && mi.getNext().getOpcode() == Opcodes.IFEQ) { + // https://github.com/JetBrains/kotlin/blob/v2.0.0-RC2/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt#L2123-L2163 + final JumpInsnNode ji = (JumpInsnNode) mi.getNext(); + output.ignore(ji, ji.label); + } + } + } + + private static boolean isComposable(final MethodNode methodNode) { + if (methodNode.invisibleAnnotations == null) { + return false; + } + for (final AnnotationNode a : methodNode.invisibleAnnotations) { + if ("Landroidx/compose/runtime/Composable;".equals(a.desc)) { + return true; + } + } + return false; + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 48b2ac196e..e5a53ba9a0 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -20,6 +20,13 @@

      Change History

      Snapshot Build @qualified.bundle.version@ (@build.date@)

      +

      New Features

      +
        +
      • Part of bytecode generated by the Kotlin Compose compiler plugin is + filtered out during generation of report + (GitHub #1616).
      • +
      +

      Release 0.8.12 (2024/03/31)

      New Features

      From 4d23aae2859e4010da0a3d5c3ff74e3e9c427548 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 8 May 2024 05:41:28 +0200 Subject: [PATCH 047/255] Add configuration for Dependabot to simplify updates of Kotlin (#1618) --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 51d2ae7554..2983a7be26 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -16,3 +16,13 @@ updates: - "component: core" allow: - dependency-name: "org.ow2.asm:*" + - package-ecosystem: "maven" + directory: "/org.jacoco.core.test.validation.kotlin" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "component: test" + - "language: kotlin" + allow: + - dependency-name: "org.jetbrains.kotlin:*" From 3bba375e0cb6416efa1a3e3682a7d83cc75a3da8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 22:33:58 +0200 Subject: [PATCH 048/255] Upgrade Kotlin to 1.9.24 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Evgeny Mandrikov --- .github/dependabot.yml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2983a7be26..0cdb098373 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,6 +23,6 @@ updates: labels: - "dependencies" - "component: test" - - "language: kotlin" + - "language: Kotlin" allow: - dependency-name: "org.jetbrains.kotlin:*" diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 00f7845aad..4d6143ece8 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 - 1.9.23 + 1.9.24 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index c652601969..5f1b6b45a7 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -476,7 +476,7 @@ - + 21 16 @@ -507,7 +507,7 @@ - + 21 16 From adf9595df74ad37f0c9c00c9a54942e326e875df Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 12 May 2024 18:45:47 +0200 Subject: [PATCH 049/255] Add filter for Kotlin inline value classes (#1475) --- .../kotlin/KotlinInlineClassTest.java | 27 +++++ .../kotlin/targets/KotlinInlineClassTarget.kt | 75 ++++++++++++++ .../filter/KotlinInlineClassFilterTest.java | 98 +++++++++++++++++++ .../internal/analysis/filter/Filters.java | 1 + .../filter/KotlinInlineClassFilter.java | 89 +++++++++++++++++ org.jacoco.doc/docroot/doc/changes.html | 3 + 6 files changed, 293 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineClassTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineClassTarget.kt create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineClassTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineClassTest.java new file mode 100644 index 0000000000..908ad78260 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineClassTest.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.KotlinInlineClassTarget; + +/** + * Test of code coverage in {@link KotlinInlineClassTarget}. + */ +public class KotlinInlineClassTest extends ValidationTestBase { + + public KotlinInlineClassTest() { + super(KotlinInlineClassTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineClassTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineClassTarget.kt new file mode 100644 index 0000000000..079fa6d9ab --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineClassTarget.kt @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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 `inline class`. + */ +object KotlinInlineClassTarget { + + interface Base { + fun base() + } + + @JvmInline + value class I1(val value: String) : Base { // assertEmpty() + + init { // assertEmpty() + nop() // assertFullyCovered() + } // assertEmpty() + + constructor() : this("") { // assertFullyCovered() + nop() // assertFullyCovered() + } // assertEmpty() + + val length: Int // assertEmpty() + get() = value.length // assertFullyCovered() + + fun f(p: String) { // assertEmpty() + nop(p) // assertFullyCovered() + } // assertFullyCovered() + + fun f(p: I1) { // assertEmpty() + nop(p) // assertFullyCovered() + } // assertFullyCovered() + + override fun base() { // assertEmpty() + nop() // assertFullyCovered() + } // assertFullyCovered() + + } // assertEmpty() + + @JvmInline + value class I2(val value: String) { // assertEmpty() + + override fun toString(): String { // assertEmpty() + return "Value: $value" // assertNotCovered() + } // assertEmpty() + + } // assertEmpty() + + @JvmStatic + fun main(args: Array) { + val i = I1() + i.value + i.length + i.f("") + i.f(i) + i.base() + + I2("") + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java new file mode 100644 index 0000000000..8fd77a0a4e --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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 org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link KotlinInlineClassFilter}. + */ +public class KotlinInlineClassFilterTest extends FilterTestBase { + + private final IFilter filter = new KotlinInlineClassFilter(); + + /** + *
      +	 * @kotlin.jvm.JvmInline
      +	 * value class Example(val value: String)
      +	 * 
      + */ + @Test + public void should_filter() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + context.classAnnotations.add("Lkotlin/jvm/JvmInline;"); + final MethodNode m = new MethodNode(0, "getValue", + "()Ljava/lang/String;", null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
      +	 * @kotlin.jvm.JvmInline
      +	 * value class Example(val value: String) {
      +	 *   fun f() { ... }
      +	 * }
      +	 * 
      + */ + @Test + public void should_not_filter_static() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + context.classAnnotations.add("Lkotlin/jvm/JvmInline;"); + final MethodNode m = new MethodNode(Opcodes.ACC_STATIC, "f-impl", "()V", + null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + + /** + *
      +	 * data class Example(val value: String)
      +	 * 
      + */ + @Test + public void should_not_filter_when_no_JvmInline_annotation() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(0, "getValue", + "()Ljava/lang/String;", null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + + @Test + public void should_not_filter_when_not_kotlin() { + context.classAnnotations.add("Lkotlin/jvm/JvmInline;"); + final MethodNode m = new MethodNode(0, "getValue", + "()Ljava/lang/String;", null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + +} 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 07268c4121..c644d9f8af 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 @@ -47,6 +47,7 @@ public static IFilter all() { new KotlinWhenStringFilter(), new KotlinUnsafeCastOperatorFilter(), new KotlinNotNullOperatorFilter(), + new KotlinInlineClassFilter(), new KotlinDefaultArgumentsFilter(), new KotlinInlineFilter(), new KotlinCoroutineFilter(), new KotlinDefaultMethodsFilter(), new KotlinComposeFilter()); 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 new file mode 100644 index 0000000000..0279e04786 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilter.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * 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 org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters methods that Kotlin compiler generates for inline classes. + * + * For + * + *
      + * @kotlin.jvm.JvmInline
      + * value class Example(val value: String) : Base {
      + *   fun f(p: String) { ... }
      + *   fun f(p: Example) { ... }
      + *   override fun base() { ... }
      + * }
      + * 
      + * + * Kotlin compiler produces + * + *
      + * @kotlin.jvm.JvmInline
      + * class Example implements Base {
      + *   private final String value;
      + *   public String getValue() { return value; }
      + *
      + *   private synthetic Example(String value) { this.value = value; }
      + *
      + *   public static String constructor-impl(String value) { ... }
      + *
      + *   public static void f-impl(String value, String p) { ... }
      + *
      + *   public static void f-ulP-heY(String value, String p) { ... }
      + *
      + *   public void base() { base-impl(value); }
      + *   public static void base-impl(String value) { ... }
      + *
      + *   public String toString() { return toString-impl(value); }
      + *   public static String toString-impl(String value) { ... }
      + *
      + *   public boolean equals(Object other) { return equals-impl(value, other); }
      + *   public static boolean equals-impl(String value, Object other) { ... }
      + *
      + *   public int hashCode() { return hashCode-impl(value); }
      + *   public static int hashCode-impl(String value) { ... }
      + *
      + *   public final synthetic String unbox-impl() { return value; }
      + *   public static synthetic Example box-impl(String value) { return new Example(value); }
      + *
      + *   public static equals-impl0(String value1, String value2) { ... }
      + * }
      + * 
      + * + * Except getter all non-synthetic non-static methods delegate to corresponding + * static methods. Non-static methods are provided for interoperability with + * Java and can not be invoked from Kotlin without reflection and so should be + * filtered out. + */ +final class KotlinInlineClassFilter implements IFilter { + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + if (!KotlinGeneratedFilter.isKotlinClass(context)) { + return; + } + if (!context.getClassAnnotations().contains("Lkotlin/jvm/JvmInline;")) { + return; + } + if ((methodNode.access & Opcodes.ACC_STATIC) != 0) { + return; + } + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index e5a53ba9a0..f958060ced 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -25,6 +25,9 @@

      New Features

    • Part of bytecode generated by the Kotlin Compose compiler plugin is filtered out during generation of report (GitHub #1616).
    • +
    • Part of bytecode generated by the Kotlin compiler for inline value classes is + filtered out during generation of report + (GitHub #1475).

    Release 0.8.12 (2024/03/31)

    From e1e6af6142f30a0210644be7585ad24424a86060 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 09:07:34 +0000 Subject: [PATCH 050/255] Bump actions/checkout from 4.1.4 to 4.1.6 (#1621) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.6. - [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/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...a5ac7e51b41094c92402da3b24376905380afc29) --- 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 911151c74b..1f005398a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: name: JDK ${{ matrix.jdk }} runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' @@ -49,7 +49,7 @@ jobs: Windows: runs-on: windows-2022 steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' From 583ee10ce516b49ca69c15d969ee2df34e8f3853 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 26 May 2024 01:32:14 +0200 Subject: [PATCH 051/255] Fix build with JDK 23 EA (#1620) --- org.jacoco.build/pom.xml | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 1a0e8448c0..053edfe778 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -762,6 +762,27 @@
    + + maven-jdk23 + + [23,) + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + + + + + + + + + + + + + + + + sources From c98f7bd01efb3cfe838bee2d65e994b1fd0f287c Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 30 May 2024 23:53:38 +0200 Subject: [PATCH 052/255] Upgrade Kotlin to 2.0.0 (#1624) --- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- .../test/validation/kotlin/KotlinWhenExpressionTest.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 4d6143ece8..b3984fc546 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 - 1.9.24 + 2.0.0 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/KotlinWhenExpressionTest.java index 5bfe46d5d5..4f0cd0b54b 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/KotlinWhenExpressionTest.java @@ -24,4 +24,9 @@ public KotlinWhenExpressionTest() { super(KotlinWhenExpressionTarget.class); } + @Override + public void all_missed_instructions_should_have_line_number() { + // https://github.com/jacoco/jacoco/issues/1557 + } + } From a6337c2f5c0f16a98a4e496a96267fb48d2f6c52 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 10 Jun 2024 10:40:02 +0200 Subject: [PATCH 053/255] Kotlin 2.0.0 supports compilation into Java 22 bytecode (#1632) --- org.jacoco.core.test.validation/pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 5f1b6b45a7..3b2a3f2359 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -476,8 +476,7 @@ - - 21 + 22 16 @@ -507,8 +506,8 @@ - - 21 + + 22 16 From 859da1c9b23a71de257718fa4bbb2c7e2d518614 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 11 Jun 2024 09:56:50 +0200 Subject: [PATCH 054/255] Add experimental support for Java 24 class files (#1631) --- .azure-pipelines/azure-pipelines.yml | 2 ++ org.jacoco.build/pom.xml | 14 +++++++++ org.jacoco.core.test.validation/pom.xml | 31 +++++++++++++++++++ .../jacoco/core/analysis/AnalyzerTest.java | 10 +++--- .../jacoco/core/instr/InstrumenterTest.java | 10 +++--- .../core/internal/instr/InstrSupportTest.java | 15 ++++----- .../core/internal/instr/InstrSupport.java | 4 +-- org.jacoco.doc/docroot/doc/changes.html | 2 ++ 8 files changed, 69 insertions(+), 19 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index 893ec71b69..2726d645ce 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -49,6 +49,8 @@ jobs: JDK_VERSION: 22 JDK 23: JDK_VERSION: 23 + JDK 24: + JDK_VERSION: 24 pool: vmImage: 'ubuntu-20.04' steps: diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 053edfe778..5c994baf78 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -928,6 +928,20 @@ + + java24-bytecode + + + bytecode.version + 24 + + + + 17 + 17 + + + ecj diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 3b2a3f2359..957bbb2704 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -528,6 +528,37 @@ + + java24-bytecode + + + bytecode.version + 24 + + + + + 22 + + 16 + + 24 + 24 + + + ../org.jacoco.core.test.validation.kotlin + ../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 0e249f5228..b4ac0c865b 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 @@ -109,7 +109,7 @@ public void should_ignore_synthetic_classes() throws Exception { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V22 + 1); + final byte[] originalBytes = createClass(Opcodes.V23 + 1); final byte[] bytes = new byte[originalBytes.length]; System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length); final long expectedClassId = CRC64.classId(bytes); @@ -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.V22 + 2); + final byte[] bytes = createClass(Opcodes.V23 + 2); try { analyzer.analyzeClass(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 68", + assertEquals("Unsupported class file major version 69", 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.V22 + 2); + final byte[] bytes = createClass(Opcodes.V23 + 2); try { analyzer.analyzeAll(new ByteArrayInputStream(bytes), "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 68", + assertEquals("Unsupported class file major version 69", e.getCause().getMessage()); } } 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 4eee4b189f..04a0ba972f 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 @@ -100,7 +100,7 @@ public void setup() throws Exception { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V22 + 1); + final byte[] originalBytes = createClass(Opcodes.V23 + 1); final byte[] bytes = new byte[originalBytes.length]; System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length); final long expectedClassId = CRC64.classId(bytes); @@ -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.V22 + 2); + final byte[] bytes = createClass(Opcodes.V23 + 2); try { instrumenter.instrument(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (final IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 68", + assertEquals("Unsupported class file major version 69", 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.V22 + 2); + final byte[] bytes = createClass(Opcodes.V23 + 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 68", + assertEquals("Unsupported class file major version 69", 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 d629bd717e..1ee2e7d74a 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_23_class() { - final byte[] bytes = createJava23Class(); + public void classReaderFor_should_read_java_24_class() { + final byte[] bytes = createJava24Class(); final ClassReader classReader = InstrSupport.classReaderFor(bytes); @@ -53,16 +53,16 @@ public void classReaderFor_should_read_java_23_class() { public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { - assertEquals(Opcodes.V22 + 1, version); + assertEquals(Opcodes.V23 + 1, version); } }, 0); - assertArrayEquals(createJava23Class(), bytes); + assertArrayEquals(createJava24Class(), bytes); } - private static byte[] createJava23Class() { + private static byte[] createJava24Class() { final ClassWriter cw = new ClassWriter(0); - cw.visit(Opcodes.V22 + 1, 0, "Foo", null, "java/lang/Object", null); + cw.visit(Opcodes.V23 + 1, 0, "Foo", null, "java/lang/Object", null); cw.visitEnd(); return cw.toByteArray(); } @@ -134,7 +134,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_ assertTrue(InstrSupport.needsFrames(Opcodes.V20)); assertTrue(InstrSupport.needsFrames(Opcodes.V21)); assertTrue(InstrSupport.needsFrames(Opcodes.V22)); - assertTrue(InstrSupport.needsFrames(Opcodes.V22 + 1)); + assertTrue(InstrSupport.needsFrames(Opcodes.V23)); + assertTrue(InstrSupport.needsFrames(Opcodes.V23 + 1)); assertTrue(InstrSupport.needsFrames(0x0100)); } 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 b9e21d1c66..858f290f4b 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.V22 + 1) { + if (originalVersion == Opcodes.V23 + 1) { // temporarily downgrade version to bypass check in ASM - setMajorVersion(Opcodes.V22, b); + setMajorVersion(Opcodes.V23, 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 f958060ced..7f5e774d96 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,6 +22,8 @@

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    New Features

      +
    • Experimental support for Java 24 class files + (GitHub #1631).
    • Part of bytecode generated by the Kotlin Compose compiler plugin is filtered out during generation of report (GitHub #1616).
    • From 303e540a4b204c2668c32c821feb3deaf524ec42 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:54:29 +0200 Subject: [PATCH 055/255] Upgrade Groovy to 3.0.21 (#1634) --- .../pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 20 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index 6732b7c5fa..a06c0d3518 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.20 + 3.0.21 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 957bbb2704..0dae8d4d8c 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -368,7 +368,7 @@ 18 - + 16 18 @@ -395,7 +395,7 @@ 19 - + 16 19 @@ -422,7 +422,7 @@ 20 - + 16 20 @@ -449,7 +449,7 @@ 21 - + 16 21 @@ -477,7 +477,7 @@ 22 - + 16 22 @@ -490,9 +490,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 @@ -508,7 +506,7 @@ 22 - + 16 23 @@ -521,7 +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 @@ -539,7 +537,7 @@ 22 - + 16 24 @@ -552,7 +550,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 5aabb2eb60bbcd05df968005f1746ba19dcd5361 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 00:19:14 +0200 Subject: [PATCH 056/255] Bump actions/checkout from 4.1.6 to 4.1.7 (#1643) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [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/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332) --- 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 1f005398a7..7eedcb7c5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: name: JDK ${{ matrix.jdk }} runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' @@ -49,7 +49,7 @@ jobs: Windows: runs-on: windows-2022 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'zulu' From 196e61a0289fda10c3054f768d041c58e4cf1b26 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:38:23 +0200 Subject: [PATCH 057/255] Add filter for Kotlin enum classes (#1625) --- .../validation/kotlin/KotlinEnumTest.java | 27 +++++ .../kotlin/KotlinWhenExpressionTest.java | 5 - .../kotlin/targets/KotlinEnumTarget.kt | 31 +++++ .../analysis/filter/KotlinEnumFilterTest.java | 113 ++++++++++++++++++ .../internal/analysis/filter/Filters.java | 1 + .../analysis/filter/KotlinEnumFilter.java | 41 +++++++ org.jacoco.doc/docroot/doc/changes.html | 3 + 7 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinEnumTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinEnumTarget.kt create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.java diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinEnumTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinEnumTest.java new file mode 100644 index 0000000000..a25aacbff0 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinEnumTest.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.KotlinEnumTarget; + +/** + * Test of code coverage in {@link KotlinEnumTarget}. + */ +public class KotlinEnumTest extends ValidationTestBase { + + public KotlinEnumTest() { + super(KotlinEnumTarget.class); + } + +} 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/KotlinWhenExpressionTest.java index 4f0cd0b54b..5bfe46d5d5 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/KotlinWhenExpressionTest.java @@ -24,9 +24,4 @@ public KotlinWhenExpressionTest() { super(KotlinWhenExpressionTarget.class); } - @Override - public void all_missed_instructions_should_have_line_number() { - // https://github.com/jacoco/jacoco/issues/1557 - } - } diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinEnumTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinEnumTarget.kt new file mode 100644 index 0000000000..4325d36190 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinEnumTarget.kt @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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 `enum class`. + */ +object KotlinEnumTarget { + + private enum class EnumClass { // assertEmpty() + E // assertFullyCovered() + } // assertEmpty() + + @JvmStatic + fun main(args: Array) { + nop(EnumClass.E) + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java new file mode 100644 index 0000000000..2c3a885132 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.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.analysis.filter; + +import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link KotlinEnumFilter}. + */ +public class KotlinEnumFilterTest extends FilterTestBase { + + private final KotlinEnumFilter filter = new KotlinEnumFilter(); + + /** + *
      +	 *   enum class Example {}
      +	 * 
      + */ + @Test + public void should_filter() { + context.superClassName = "java/lang/Enum"; + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getEntries", + "()Lkotlin/enums/EnumEntries;", null, null); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", + "Lkotlin/enums/EnumEntries;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + @Test + public void should_not_filter_when_not_Enum() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getEntries", + "()Lkotlin/enums/EnumEntries;", null, null); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", + "Lkotlin/enums/EnumEntries;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + + @Test + public void should_not_filter_when_not_Kotlin() { + context.superClassName = "java/lang/Enum"; + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getEntries", + "()Lkotlin/enums/EnumEntries;", null, null); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", + "Lkotlin/enums/EnumEntries;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + + @Test + public void should_not_filter_when_not_getEntries_name() { + context.superClassName = "java/lang/Enum"; + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "get", + "()Lkotlin/enums/EnumEntries;", null, null); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", + "Lkotlin/enums/EnumEntries;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + + @Test + public void should_not_filter_when_not_getEntries_descriptor() { + context.superClassName = "java/lang/Enum"; + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getEntries", + "(I)Lkotlin/enums/EnumEntries;", null, null); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", + "Lkotlin/enums/EnumEntries;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + +} 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 c644d9f8af..de1a1f3612 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 @@ -43,6 +43,7 @@ public static IFilter all() { new ExhaustiveSwitchFilter(), // new RecordPatternFilter(), // new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(), + new KotlinEnumFilter(), // new KotlinLateinitFilter(), new KotlinWhenFilter(), new KotlinWhenStringFilter(), new KotlinUnsafeCastOperatorFilter(), 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 new file mode 100644 index 0000000000..5d9891d3f9 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilter.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: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters method getEntries that Kotlin compiler creates for + * enums. + */ +final class KotlinEnumFilter implements IFilter { + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + if (!"java/lang/Enum".equals(context.getSuperClassName())) { + return; + } + if (!KotlinGeneratedFilter.isKotlinClass(context)) { + return; + } + if (!"getEntries".equals(methodNode.name)) { + return; + } + if (!"()Lkotlin/enums/EnumEntries;".equals(methodNode.desc)) { + return; + } + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 7f5e774d96..7f8347b791 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).
    • +
    • Method getEntries generated by the Kotlin compiler for enum + classes is filtered out during generation of report + (GitHub #1625).

    Release 0.8.12 (2024/03/31)

    From ebad1872760568d5c6cc60f65c0a2034dcb66691 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 20:43:17 +0000 Subject: [PATCH 058/255] Bump actions/upload-artifact from 4.3.3 to 4.3.4 (#1645) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.3 to 4.3.4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65462800fd760344b1a7b4382951275a0abb4808...0b2256b8c012f0828dc542b3febcab082c67f72b) --- 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 7eedcb7c5b..60fddb7341 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: mvn -V -B -e --no-transfer-progress \ verify -Djdk.version=6 -Dbytecode.version=5 \ --toolchains=toolchains.xml - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 id: artifact-upload-step with: name: jacoco From 68325881fd3119a1f7952b9d8466208d61aa14fa Mon Sep 17 00:00:00 2001 From: Marharyta Date: Tue, 9 Jul 2024 23:14:56 +0200 Subject: [PATCH 059/255] Version of sonar-maven-plugin should be specified explicitly --- org.jacoco.build/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 5c994baf78..19d75bb81b 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -451,6 +451,11 @@ spotless-maven-plugin 2.41.1 + + org.sonarsource.scanner.maven + sonar-maven-plugin + 4.0.0.4121 + From 7589f79f3a7329b77c605a11a6825aed8b812f0f Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:26:42 +0200 Subject: [PATCH 060/255] Fix typo (#1647) --- org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java index 50ca901675..ca398e9596 100644 --- a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java +++ b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java @@ -18,7 +18,7 @@ */ public interface ISourceNode extends ICoverageNode { - /** Place holder for unknown lines (no debug information) */ + /** Placeholder for unknown lines (no debug information) */ int UNKNOWN_LINE = -1; /** From 77d2af5ec31faf04419d945e1a0c34da49f8a702 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:32:45 +0200 Subject: [PATCH 061/255] `mvn -Decj=false` should not activate the use of ECJ (#1648) --- org.jacoco.build/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 19d75bb81b..8476939e33 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -953,6 +953,7 @@ ecj + true From fce2e5b6ef1cd48c0cb3e436d2454389fceeb637 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:17:09 +0200 Subject: [PATCH 062/255] Update KotlinCoroutineFilter for Kotlin 1.6 (#1283) --- .../kotlin/targets/KotlinCoroutineTarget.kt | 7 +++ .../filter/KotlinCoroutineFilterTest.java | 63 +++++++++++++++++++ .../filter/KotlinCoroutineFilter.java | 33 +++++++--- org.jacoco.doc/docroot/doc/changes.html | 3 + 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt index 7a5def6d7d..0c5d7ce030 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt @@ -34,6 +34,12 @@ object KotlinCoroutineTarget { nop() // assertFullyCovered() } + private fun suspendingLambdaWithoutSuspensionPoints() { + runBlocking { // assertFullyCovered() + nop() // assertFullyCovered() + } // assertFullyCovered() + } + @JvmStatic fun main(args: Array) { @@ -45,6 +51,7 @@ object KotlinCoroutineTarget { suspendingFunctionWithTailCallOptimization() } // assertFullyCovered() + suspendingLambdaWithoutSuspensionPoints() } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java index 19209ebd66..12a22369d1 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java @@ -448,4 +448,67 @@ public void should_filter_suspending_functions_with_tail_call_optimization() { assertIgnored(range1, range2); } + /** + *
    +	 *     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 063/255] 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 064/255] 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 065/255] 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 066/255] 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 067/255] 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 068/255] 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
    +	 * 
    + * + *
    +	 * import a.testInline
    +	 *
    +	 * fun main() {
    +	 *   testInline() // line 4
    +	 * }
    +	 * 
    + */ + @Test + public void should_filter_when_inlined_with_same_file_name_and_line_number() { + context.className = "ExampleKt"; + context.sourceFileName = "Example.kt"; + context.sourceDebugExtension = "" // + + "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" // + + "+ 2 Example.kt\n" // FileID=2,FileName=Example.kt + + "a/ExampleKt\n" // + + "*L\n" // LineSection + + "1#1,6:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=6,OutputStartLine=1 + + "7#2:7\n" // InputStartLine=7,LineFileID=2,OutputStartLine=7 + + "*S KotlinDebug"; // StratumID=KotlinDebug + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + + Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(4, label0); + m.visitInsn(Opcodes.ICONST_0); + m.visitVarInsn(Opcodes.ISTORE, 0); + Label label1 = new Label(); + m.visitLabel(label1); + m.visitLineNumber(7, label1); + shouldIgnorePrevious(m); + m.visitInsn(Opcodes.NOP); + shouldIgnorePrevious(m); + Label label2 = new Label(); + m.visitLabel(label2); + shouldIgnorePrevious(m); + m.visitLineNumber(5, label2); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(expectedRanges.toArray(new Range[0])); + } + + /** + *
    +	 * inline fun example(crossinline lambda: () -> Unit): () -> Unit {
    +	 *   return {
    +	 *     lambda()
    +	 *   }
    +	 * }
    +	 *
    +	 * fun callsite() {
    +	 *   example {
    +	 *   }()
    +	 * }
    +	 * 
    + */ + @Test + public void should_filter_all_lines() { + context.className = "ExampleKt$callsite$$inlined$example$1"; + context.sourceFileName = "Example.kt"; + context.sourceDebugExtension = "" // + + "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 + + "ExampleKt$example$1\n" // + + "+ 2 Example.kt\n" // FileID=2 + + "ExampleKt\n" // + + "*L\n" // LineSection + + "1#1,11:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=11,OutputStartLine=1 + + "9#2:12\n" // InputStartLine=9,LineFileID=2,OutputStartLine=12 + + "*E\n"; // EndSection + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + + Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(3, label0); + m.visitInsn(Opcodes.ICONST_0); + m.visitVarInsn(Opcodes.ISTORE, 1); + Label label1 = new Label(); + m.visitLabel(label1); + m.visitLineNumber(12, label1); + m.visitInsn(Opcodes.NOP); + Label label2 = new Label(); + m.visitLabel(label2); + m.visitLineNumber(3, label2); + m.visitInsn(Opcodes.NOP); + Label label3 = new Label(); + m.visitLabel(label3); + m.visitLineNumber(4, label3); + m.visitInsn(Opcodes.RETURN); + + for (AbstractInsnNode i = m.instructions.getFirst() + .getNext(); i != null; i = i.getNext()) { + expectedRanges.add(new Range(i, i)); + } + + filter.filter(m, context, output); + + assertIgnored(expectedRanges.toArray(new Range[0])); + } + @Test public void should_not_parse_SourceDebugExtension_attribute_when_no_kotlin_metadata_annotation() { context.sourceDebugExtension = "SMAP"; @@ -265,32 +390,9 @@ public void should_throw_exception_when_unexpected_FileInfo() { } } - @Test - public void should_throw_exception_when_no_SourceFileId_for_SourceFile() { - context.sourceFileName = "example.kt"; - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - context.sourceDebugExtension = "" // - + "SMAP\n" // - + "example.kt\n" // - + "Kotlin\n" // - + "*S Kotlin\n" // - + "*F\n" // - + "+ 1 another.kt\n" // - + "AnotherKt\n" // - + "*L\n" // - + "*E\n"; - - try { - filter.filter(m, context, output); - fail("exception expected"); - } catch (final IllegalStateException e) { - assertEquals("Unexpected SMAP FileSection", e.getMessage()); - } - } - @Test public void should_throw_exception_when_unexpected_LineInfo() { + context.className = "Callsite"; context.sourceFileName = "callsite.kt"; context.sourceDebugExtension = "" // + "SMAP\n" // 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 60fa490e01..43e328e977 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 @@ -42,7 +42,7 @@ public void filter(final MethodNode methodNode, if (firstGeneratedLineNumber == -1) { firstGeneratedLineNumber = getFirstGeneratedLineNumber( - context.getSourceFileName(), + context.getClassName(), context.getSourceFileName(), context.getSourceDebugExtension()); } @@ -57,7 +57,8 @@ public void filter(final MethodNode methodNode, } } - private static int getFirstGeneratedLineNumber(final String sourceFileName, + private static int getFirstGeneratedLineNumber( + final String currentClassName, final String sourceFileName, final String smap) { try { final BufferedReader br = new BufferedReader( @@ -74,22 +75,19 @@ private static int getFirstGeneratedLineNumber(final String sourceFileName, final BitSet sourceFileIds = new BitSet(); String line; while (!"*L".equals(line = br.readLine())) { - // AbsoluteFileName - br.readLine(); - final Matcher m = FILE_INFO_PATTERN.matcher(line); if (!m.matches()) { throw new IllegalStateException( "Unexpected SMAP line: " + line); } - final String fileName = m.group(2); - if (fileName.equals(sourceFileName)) { + // 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))); } } - if (sourceFileIds.isEmpty()) { - throw new IllegalStateException("Unexpected SMAP FileSection"); - } // LineSection int min = Integer.MAX_VALUE; while (true) { diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 2dec020d62..2dd5dcb1b5 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -38,6 +38,12 @@

    New Features

    (GitHub #1625). +

    Fixed bugs

    +
      +
    • Fixed interpretation of Kotlin SMAP + (GitHub #1525).
    • +
    +

    Release 0.8.12 (2024/03/31)

    New Features

    From c4cae9087f657945291f15813f4b8566275fb9ba Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 31 Jul 2024 09:27:41 +0200 Subject: [PATCH 069/255] Fix javadoc (#1661) Incorrect since creation in commit 2f5a2fc86a1148674bd1d661111c621cfa912a6b in JaCoCo version 0.1.0 --- .../src/org/jacoco/report/internal/ReportOutputFolder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java index 8fed4bf306..d98023ddc3 100644 --- a/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java +++ b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java @@ -83,8 +83,8 @@ public ReportOutputFolder subFolder(final String name) { * Creates a new file in this folder with the given local name. * * @param name - * name of the sub-folder - * @return handle for output into the sub-folder + * name of the file + * @return stream for output into the file * @throws IOException * if the file creation fails */ From b8197762cfa2adb7ebddcc9ea5c3f5849f1ebf0a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 3 Aug 2024 23:18:47 +0200 Subject: [PATCH 070/255] Extract SMAP parser from KotlinInlineFilter (#1663) --- .../filter/KotlinInlineFilterTest.java | 106 --------- .../analysis/filter/KotlinSMAPTest.java | 209 ++++++++++++++++++ .../analysis/filter/KotlinInlineFilter.java | 94 +------- .../internal/analysis/filter/KotlinSMAP.java | 182 +++++++++++++++ 4 files changed, 401 insertions(+), 190 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSMAPTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSMAP.java 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 73b77a097e..161faea31f 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 @@ -12,9 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - import java.util.ArrayList; import java.util.List; @@ -166,48 +163,6 @@ public void should_filter_when_in_same_file() { assertIgnored(expectedRanges.toArray(new Range[0])); } - /** - * See KT-37704 - * - *
    -	 * inline fun f() {}
    -	 * fun g() = f()
    -	 * 
    - */ - @Test - public void should_filter_without_parsing_KotlinDebug_stratum() { - context.className = "ExampleKt"; - context.sourceFileName = "Example.kt"; - context.sourceDebugExtension = "" // - + "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 - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - - m.visitLineNumber(2, new Label()); - m.visitInsn(Opcodes.ICONST_0); - m.visitVarInsn(Opcodes.ISTORE, 0); - m.visitLineNumber(4, new Label()); - shouldIgnorePrevious(m); - m.visitInsn(Opcodes.NOP); - shouldIgnorePrevious(m); - m.visitLineNumber(3, new Label()); - m.visitInsn(Opcodes.RETURN); - - filter.filter(m, context, output); - - assertIgnored(expectedRanges.toArray(new Range[0])); - } - /** *
     	 * package a;
    @@ -354,67 +309,6 @@ public void should_not_filter_when_no_SourceDebugExtension_attribute() {
     		assertIgnored();
     	}
     
    -	@Test
    -	public void should_throw_exception_when_SMAP_incomplete() {
    -		context.sourceDebugExtension = "" //
    -				+ "SMAP\n";
    -		context.classAnnotations
    -				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
    -
    -		try {
    -			filter.filter(m, context, output);
    -			fail("exception expected");
    -		} catch (final IllegalStateException e) {
    -			assertEquals("Unexpected SMAP line: null", e.getMessage());
    -		}
    -	}
    -
    -	@Test
    -	public void should_throw_exception_when_unexpected_FileInfo() {
    -		context.sourceFileName = "callsite.kt";
    -		context.sourceDebugExtension = "" //
    -				+ "SMAP\n" //
    -				+ "callsite.kt\n" //
    -				+ "Kotlin\n" //
    -				+ "*S Kotlin\n" //
    -				+ "*F\n" //
    -				+ "xxx";
    -		context.classAnnotations
    -				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
    -
    -		try {
    -			filter.filter(m, context, output);
    -			fail("exception expected");
    -		} catch (final IllegalStateException e) {
    -			assertEquals("Unexpected SMAP line: xxx", e.getMessage());
    -		}
    -	}
    -
    -	@Test
    -	public void should_throw_exception_when_unexpected_LineInfo() {
    -		context.className = "Callsite";
    -		context.sourceFileName = "callsite.kt";
    -		context.sourceDebugExtension = "" //
    -				+ "SMAP\n" //
    -				+ "callsite.kt\n" //
    -				+ "Kotlin\n" //
    -				+ "*S Kotlin\n" //
    -				+ "*F\n" //
    -				+ "+ 1 callsite.kt\n" //
    -				+ "Callsite\n" //
    -				+ "*L\n" //
    -				+ "xxx";
    -		context.classAnnotations
    -				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
    -
    -		try {
    -			filter.filter(m, context, output);
    -			fail("exception expected");
    -		} catch (final IllegalStateException e) {
    -			assertEquals("Unexpected SMAP line: xxx", e.getMessage());
    -		}
    -	}
    -
     	private final List expectedRanges = new ArrayList();
     
     	private void shouldIgnorePrevious(final MethodNode m) {
    diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSMAPTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSMAPTest.java
    new file mode 100644
    index 0000000000..f6a00115da
    --- /dev/null
    +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSMAPTest.java
    @@ -0,0 +1,209 @@
    +/*******************************************************************************
    + * 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 static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.fail;
    +
    +import org.junit.Test;
    +
    +/**
    + * Unit test for {@link KotlinSMAP}.
    + */
    +public class KotlinSMAPTest {
    +
    +	/**
    +	 * 
    +	 * // A.kt
    +	 * package a
    +	 * inline fun f() {} // line 3
    +	 * 
    + * + *
    +	 * // B.kt
    +	 * package b
    +	 * fun callsite() = f() // line 3
    +	 * 
    + */ + @Test + public void should_parse() { + final KotlinSMAP smap = new KotlinSMAP("B.kt", "SMAP\n" // + + "B.kt\n" // OutputFileName=B.kt + + "Kotlin\n" // DefaultStratumId=Kotlin + + "*S Kotlin\n" // StratumID=Kotlin + + "*F\n" // FileSection + + "+ 1 B.kt\n" // FileID=1,FileName=B.kt + + "b/BKt\n" // ClassName=b/BKt + + "+ 2 A.kt\n" // FileID=2,FileName=A.kt + + "a/AKt\n" // ClassName=a/AKt + + "*L\n" // LineSection + + "1#1,4:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=4,OutputStartLine=1 + + "3#2:5\n" // InputStartLine=3,LineFileID=2,RepeatCount=,OutputStartLine=5 + + "*E\n"); // EndSection + assertEquals(2, smap.mappings().size()); + KotlinSMAP.Mapping mapping = smap.mappings().get(0); + assertEquals("b/BKt", mapping.inputClassName()); + assertEquals(1, mapping.inputStartLine()); + assertEquals(4, mapping.repeatCount()); + assertEquals(1, mapping.outputStartLine()); + mapping = smap.mappings().get(1); + assertEquals("a/AKt", mapping.inputClassName()); + assertEquals(3, mapping.inputStartLine()); + assertEquals(1, mapping.repeatCount()); + assertEquals(5, mapping.outputStartLine()); + } + + /** + * See KT-37704 + * + *
    +	 * inline fun f() {}
    +	 * fun g() = f()
    +	 * 
    + */ + @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 071/255] 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 072/255] 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 073/255] 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 074/255] 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 075/255] 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 @@ - + 22 16 @@ -535,7 +535,7 @@ - + 22 16 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 076/255] 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 077/255] 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 - + 16 18 @@ -395,7 +395,7 @@ 19 - + 16 19 @@ -422,7 +422,7 @@ 20 - + 16 20 @@ -449,7 +449,7 @@ 21 - + 16 21 @@ -477,7 +477,7 @@ 22 - + 16 22 @@ -506,7 +506,7 @@ 22 - + 16 23 @@ -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 - + 16 24 @@ -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 078/255] 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 @@

    Fixed bugs

    (GitHub #1525). +

    Non-functional Changes

    +
      +
    • JaCoCo build now requires at least Maven 3.6.3 + (GitHub #1681).
    • +
    +

    Release 0.8.12 (2024/03/31)

    New Features

    diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html index cc787d2405..1d827fe4f6 100644 --- a/org.jacoco.doc/docroot/doc/environment.html +++ b/org.jacoco.doc/docroot/doc/environment.html @@ -76,7 +76,7 @@

    Build

    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 079/255] 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 080/255] 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).

    Non-functional Changes

    diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java index f63fe8c99d..837d81a3c5 100644 --- a/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java +++ b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java @@ -52,26 +52,26 @@ public void testSameInstance() { @Test public void testReplaceIllegalCharactersNonUnique() { - assertEquals("F__", nfn.getFileName("F__")); - assertEquals("F__~1", nfn.getFileName("F**")); - assertEquals("F__~2", nfn.getFileName("F??")); + assertEquals("F__.html", nfn.getFileName("F__.html")); + assertEquals("1~F__.html", nfn.getFileName("F**.html")); + assertEquals("2~F__.html", nfn.getFileName("F??.html")); // Mapping must be reproducible - assertEquals("F__", nfn.getFileName("F__")); - assertEquals("F__~1", nfn.getFileName("F**")); - assertEquals("F__~2", nfn.getFileName("F??")); + assertEquals("F__.html", nfn.getFileName("F__.html")); + assertEquals("1~F__.html", nfn.getFileName("F**.html")); + assertEquals("2~F__.html", nfn.getFileName("F??.html")); } @Test public void testCaseAware() { - assertEquals("Hello", nfn.getFileName("Hello")); - assertEquals("HELLO~1", nfn.getFileName("HELLO")); - assertEquals("HeLLo~2", nfn.getFileName("HeLLo")); + assertEquals("Hello.html", nfn.getFileName("Hello.html")); + assertEquals("1~HELLO.html", nfn.getFileName("HELLO.html")); + assertEquals("2~HeLLo.html", nfn.getFileName("HeLLo.html")); // Mapping must be reproducible - assertEquals("Hello", nfn.getFileName("Hello")); - assertEquals("HELLO~1", nfn.getFileName("HELLO")); - assertEquals("HeLLo~2", nfn.getFileName("HeLLo")); + assertEquals("Hello.html", nfn.getFileName("Hello.html")); + assertEquals("1~HELLO.html", nfn.getFileName("HELLO.html")); + assertEquals("2~HeLLo.html", nfn.getFileName("HeLLo.html")); } } diff --git a/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java index f820f10d10..192ca90972 100644 --- a/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java +++ b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java @@ -31,7 +31,7 @@ *
  • File names are case aware, i.e. the same file name but with different * upper/lower case characters is not possible.
  • *
  • If unique filenames can't directly created from the ids, additional - * suffixes are appended.
  • + * prefixes are prepended. * */ class NormalizedFileNames { @@ -81,7 +81,7 @@ private String ensureUniqueness(final String s) { String lower = unique.toLowerCase(Locale.ENGLISH); int idx = 1; while (usedNames.contains(lower)) { - unique = s + '~' + idx++; + unique = (idx++) + "~" + s; lower = unique.toLowerCase(Locale.ENGLISH); } usedNames.add(lower); From 36896b919e97cda9f96938c3eafd56c4b808b592 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:38:45 +0200 Subject: [PATCH 081/255] Bump actions/upload-artifact from 4.3.5 to 4.3.6 (#1682) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.5 to 4.3.6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/89ef406dd8d7e03cfd12d9e0a4a378f454709029...834a144ee995460fba8ed112a2fc961b36a5ec5a) --- 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 67b3a08b9b..366d04eb93 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@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5 + - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 id: artifact-upload-step with: name: jacoco From 7d01bcad9e7ce19dc5b7c8ba316abdb8d530dc8a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 15 Aug 2024 18:55:47 +0200 Subject: [PATCH 082/255] Upgrade JUnit to 4.13.2 (#1687) --- 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 3e07eeb632..fe18735220 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -142,7 +142,7 @@ 9.7 1.9.16 2.0.28 - 4.13.1 + 4.13.2 20100721 From 55c03b848279ba492d8645f1febe2133ed6d11d7 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 15 Aug 2024 19:22:22 +0200 Subject: [PATCH 083/255] Upgrade AntUnit to 1.4.1 (#1686) --- 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 fe18735220..c28ccd159f 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -237,7 +237,7 @@ org.apache.ant ant-antunit - 1.4 + 1.4.1 args4j From 7d9b69e003da6ba5d5e8cc87e85cca2b03c3b66e Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 22 Aug 2024 22:13:57 +0200 Subject: [PATCH 084/255] Generate HTML reports for validation tests (#1690) --- org.jacoco.core.test/pom.xml | 2 +- .../test/validation/ValidationTestBase.java | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index 45a40d90e5..0f2a666e6a 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -31,7 +31,7 @@ ${project.groupId} - org.jacoco.core + org.jacoco.report org.ow2.asm 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 c160e809c1..89423ee1fa 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 @@ -15,22 +15,31 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import org.jacoco.core.analysis.Analyzer; import org.jacoco.core.analysis.CoverageBuilder; +import org.jacoco.core.analysis.IBundleCoverage; import org.jacoco.core.analysis.ICounter; import org.jacoco.core.analysis.ILine; import org.jacoco.core.data.ExecutionData; import org.jacoco.core.data.ExecutionDataStore; +import org.jacoco.core.data.SessionInfo; import org.jacoco.core.internal.analysis.CounterImpl; import org.jacoco.core.test.InstrumentingLoader; import org.jacoco.core.test.TargetLoader; import org.jacoco.core.test.validation.Source.Line; import org.jacoco.core.test.validation.targets.Stubs; +import org.jacoco.report.DirectorySourceFileLocator; +import org.jacoco.report.FileMultiReportOutput; +import org.jacoco.report.IReportVisitor; +import org.jacoco.report.ISourceFileLocator; +import org.jacoco.report.html.HTMLFormatter; import org.junit.Before; import org.junit.Test; import org.junit.runners.model.MultipleFailureException; @@ -56,6 +65,8 @@ public abstract class ValidationTestBase { private Source source; + private IBundleCoverage bundle; + private InstrumentingLoader loader; protected ValidationTestBase(final Class target) { @@ -86,7 +97,9 @@ private void analyze(final ExecutionDataStore store) throws IOException { for (ExecutionData data : store.getContents()) { analyze(analyzer, data); } - source = Source.load(target, builder.getBundle("Test")); + final String testClassSimpleName = getClass().getSimpleName(); + bundle = builder.getBundle(testClassSimpleName); + source = Source.load(target, bundle); } private void analyze(final Analyzer analyzer, final ExecutionData data) @@ -96,6 +109,22 @@ private void analyze(final Analyzer analyzer, final ExecutionData data) analyzer.analyzeClass(bytes, data.getName()); } + /** + * Generates HTML report. + */ + @Test + public final void generate_html_report() throws IOException { + final File destination = new File("target/reports/" + bundle.getName()); + final IReportVisitor visitor = new HTMLFormatter() + .createVisitor(new FileMultiReportOutput(destination)); + visitor.visitInfo(Collections. emptyList(), + Collections. emptyList()); + final ISourceFileLocator sourceFileLocator = new DirectorySourceFileLocator( + new File("src"), "UTF-8", 4); + visitor.visitBundle(bundle, sourceFileLocator); + visitor.visitEnd(); + } + /** * All single line comments are interpreted as statements in the following * format: From 517ecddb6eb3e69d33834ae4f12b78dc0f33583f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 19:34:05 +0200 Subject: [PATCH 085/255] Upgrade Kotlin to 2.0.20 (#1693) 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 a420a3e6fb..42e1af9c00 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.10 + 2.0.20 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index c9b4001d9a..2dbd7861fd 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -504,7 +504,7 @@ - + 22 16 @@ -533,7 +533,7 @@ - + 22 16 From 5dda5f4ea92f8538dcc5bd302ead377ef8c4d400 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:18:07 +0200 Subject: [PATCH 086/255] Bump actions/upload-artifact from 4.3.6 to 4.4.0 (#1695) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.6 to 4.4.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/834a144ee995460fba8ed112a2fc961b36a5ec5a...50769540e7f4bd5e21e526ee35c689e35e0d6874) --- updated-dependencies: - dependency-name: actions/upload-artifact 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 366d04eb93..2f388c40cf 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@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 id: artifact-upload-step with: name: jacoco From 831ecd609e17a3a5f8e114134fa0ce1d2071c6bd Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 5 Sep 2024 00:08:08 +0200 Subject: [PATCH 087/255] Calculate line coverage for Kotlin inline functions (#1670) --- .../kotlin/KotlinCrossinlineTest.java | 5 - .../kotlin/KotlinDefaultMethodsTest.java | 6 - .../validation/kotlin/KotlinInlineTest.java | 5 - .../kotlin/targets/KotlinCrossinlineTarget.kt | 12 +- .../kotlin/targets/KotlinInlineTarget.kt | 12 +- .../core/analysis/CoverageBuilderTest.java | 30 +++++ .../internal/analysis/ClassAnalyzerTest.java | 103 ++++++++++++++++++ .../analysis/ClassCoverageImplTest.java | 50 +++++++++ .../analysis/MethodCoverageImplTest.java | 55 ++++++++++ .../internal/analysis/SourceNodeImplTest.java | 26 +++++ .../filter/KotlinGeneratedFilterTest.java | 27 +++++ .../test/validation/ValidationTestBase.java | 4 +- .../jacoco/core/analysis/CoverageBuilder.java | 40 +++++-- .../core/internal/analysis/ClassAnalyzer.java | 58 +++++++++- .../internal/analysis/ClassCoverageImpl.java | 42 +++++++ .../internal/analysis/MethodCoverageImpl.java | 12 ++ .../internal/analysis/SourceNodeImpl.java | 35 ++++++ .../filter/KotlinGeneratedFilter.java | 8 +- .../internal/analysis/filter/KotlinSMAP.java | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 + 20 files changed, 494 insertions(+), 40 deletions(-) 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 index ce1f317372..c4c442d126 100644 --- 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 @@ -24,9 +24,4 @@ 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/KotlinDefaultMethodsTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultMethodsTest.java index 3ec1480182..8c92ad2d16 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultMethodsTest.java +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultMethodsTest.java @@ -24,10 +24,4 @@ public KotlinDefaultMethodsTest() { super(KotlinDefaultMethodsTarget.class); } - @Override - public void all_missed_instructions_should_have_line_number() { - // instructions without line numbers - // corresponding to non-executed default implementations - } - } diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java index 43d9e57b58..6a66b25b08 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java @@ -24,9 +24,4 @@ public KotlinInlineTest() { super(KotlinInlineTargetKt.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 index f0a58015de..5454236f4b 100644 --- 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 @@ -20,17 +20,19 @@ import org.jacoco.core.test.validation.targets.Stubs.nop object KotlinCrossinlineTarget { inline fun example(crossinline lambda: () -> Unit): () -> Unit { // assertEmpty() - return { // assertNotCovered() - lambda() // assertEmpty() - } // assertEmpty() + return { // assertFullyCovered() + requireCrossinline { lambda() } // assertFullyCovered() + } // assertFullyCovered() } // assertEmpty() + fun requireCrossinline(lambda: () -> Unit) = lambda() + @JvmStatic fun main(args: Array) { example { // assertFullyCovered() - nop() // assertEmpty() - }() // assertEmpty() + nop() // assertFullyCovered() + }() // assertFullyCovered() } diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt index b98e6dc56d..ed21d20b92 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt @@ -22,15 +22,15 @@ fun main(args: Array) { KotlinInlineTarget.main(args) } -inline fun inlined_top_level() { - nop() // assertNotCovered() -} +inline fun inlined_top_level() { // assertEmpty() + nop() // assertFullyCovered() +} // assertFullyCovered() object KotlinInlineTarget { - inline fun inlined() { - nop() // assertNotCovered() - } + inline fun inlined() { // assertEmpty() + nop() // assertFullyCovered() + } // assertFullyCovered() @JvmStatic fun main(args: Array) { diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java index fcd862f2f9..03b9bb7e96 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java @@ -26,6 +26,7 @@ import org.jacoco.core.internal.analysis.ClassCoverageImpl; import org.jacoco.core.internal.analysis.CounterImpl; import org.jacoco.core.internal.analysis.MethodCoverageImpl; +import org.jacoco.core.internal.analysis.SourceNodeImpl; import org.junit.Before; import org.junit.Test; @@ -244,6 +245,35 @@ public void testGetNoMatchClasses() { assertEquals(expected, actual); } + @Test + public void testApplyFragment() { + coverageBuilder.visitCoverage(new ClassCoverageImpl("FooKt", 0, false) { + { + setSourceFileName("Foo.kt"); + addMethod(new MethodCoverageImpl("foo", "()V", null) { + { + increment(CounterImpl.COUNTER_1_0, + CounterImpl.COUNTER_0_0, 42); + } + }); + setFragments(Collections. singletonList( + new SourceNodeImpl(null, "FooKt") { + { + increment(CounterImpl.COUNTER_0_1, + CounterImpl.COUNTER_0_0, 42); + } + })); + } + }); + + final IClassCoverage c = coverageBuilder.getClasses().iterator().next(); + assertEquals(1, c.getClassCounter().getCoveredCount()); + + final ISourceFileCoverage s = coverageBuilder.getSourceFiles() + .iterator().next(); + assertEquals(1, s.getClassCounter().getCoveredCount()); + } + private Set getNames(Collection nodes) { Set result = new HashSet(); for (ICoverageNode n : nodes) { 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 44186568a6..018bf0fbe7 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 @@ -14,12 +14,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import org.jacoco.core.internal.flow.MethodProbesVisitor; import org.jacoco.core.internal.instr.InstrSupport; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Attribute; +import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.MethodNode; @@ -97,4 +99,105 @@ public void should_collect_attributes() { assertTrue(analyzer.getClassAttributes().contains("foo")); } + /** + *
    +	 * class Foo {
    +	 *   inline fun f() {}
    +	 *   fun g() = f()
    +	 * }
    +	 * 
    + */ + @Test + public void testCalculateFragments() { + analyzer.visitSource("Foo.kt", "SMAP\n" // + + "Foo.kt\n" // + + "Kotlin\n" // + + "*S Kotlin\n" // + + "*F\n" // + + "+ 1 Foo.kt\n" // + + "Foo\n" // + + "*L\n" // + + "1#1,4:1\n" // + + "2#1:6\n" // + + "*E\n"); + analyzer.visitAnnotation("Lkotlin/Metadata;", false); + MethodNode mn = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "foo", + "()V", null, null) { + { + final Label label = new Label(); + visitLabel(label); + visitLineNumber(2, label); + visitInsn(Opcodes.RETURN); + } + }; + MethodProbesVisitor mv = analyzer.visitMethod(mn.access, mn.name, + mn.desc, mn.signature, mn.exceptions.toArray(new String[0])); + mv.accept(mn, mv); + mn = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "bar", "()V", null, + null) { + { + final Label label = new Label(); + visitLabel(label); + visitLineNumber(6, label); + visitInsn(Opcodes.RETURN); + } + }; + mv = analyzer.visitMethod(mn.access, mn.name, mn.desc, mn.signature, + mn.exceptions.toArray(new String[0])); + mv.accept(mn, mv); + analyzer.visitEnd(); + + final SourceNodeImpl fragment = coverage.getFragments().iterator() + .next(); + assertEquals(fragment.getName(), "Foo"); + assertEquals(CounterImpl.COUNTER_1_0, + fragment.getLine(2).getInstructionCounter()); + } + + /** + * @see #should_not_parse_absent_SourceDebugExtension_attribute_when_kotlin() + * @see #should_parse_SourceDebugExtension_attribute_when_Kotlin() + */ + @Test + public void should_not_parse_SourceDebugExtension_attribute_when_not_Kotlin() { + analyzer.visitSource("Foo.kt", "SMAP\n"); + final MethodNode mn = new MethodNode(0, "foo", "()V", null, null); + final MethodProbesVisitor mv = analyzer.visitMethod(mn.access, mn.name, + mn.desc, mn.signature, mn.exceptions.toArray(new String[0])); + mv.accept(mn, mv); + } + + /** + * @see #should_not_parse_SourceDebugExtension_attribute_when_not_Kotlin() + * @see #should_parse_SourceDebugExtension_attribute_when_Kotlin() + */ + @Test + public void should_not_parse_absent_SourceDebugExtension_attribute_when_kotlin() { + analyzer.visitSource("Foo.kt", null); + analyzer.visitAnnotation("Lkotlin/Metadata;", false); + final MethodNode mn = new MethodNode(0, "foo", "()V", null, null); + final MethodProbesVisitor mv = analyzer.visitMethod(mn.access, mn.name, + mn.desc, mn.signature, mn.exceptions.toArray(new String[0])); + mv.accept(mn, mv); + } + + /** + * @see #should_not_parse_SourceDebugExtension_attribute_when_not_Kotlin() + * @see #should_not_parse_absent_SourceDebugExtension_attribute_when_kotlin() + */ + @Test + public void should_parse_SourceDebugExtension_attribute_when_Kotlin() { + analyzer.visitSource("Foo.kt", "SMAP\n"); + analyzer.visitAnnotation("Lkotlin/Metadata;", false); + final MethodNode mn = new MethodNode(0, "foo", "()V", null, null); + final MethodProbesVisitor mv = analyzer.visitMethod(mn.access, mn.name, + mn.desc, mn.signature, mn.exceptions.toArray(new String[0])); + try { + mv.accept(mn, mv); + fail("exception expected"); + } catch (Exception e) { + // expected + } + } + } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java index 7ae5c82fab..43a4cc39c4 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java @@ -15,8 +15,10 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Collection; import java.util.Collections; import org.jacoco.core.analysis.ICoverageNode; @@ -43,6 +45,7 @@ public void testDefaults() { assertEquals(12345, node.getId()); assertFalse(node.isNoMatch()); assertEquals(Collections.emptyList(), node.getMethods()); + assertSame(Collections.emptyList(), node.getFragments()); } @Test @@ -113,6 +116,53 @@ public void testAddMethodCovered() { assertEquals(CounterImpl.COUNTER_0_1, node.getClassCounter()); } + /** + * {@link ClassCoverageImpl#setFragments(Collection)} + * {@link ClassCoverageImpl#getFragments()} + */ + @Test + public void testSetFragments() { + final Collection fragments = Collections + .singletonList(new SourceNodeImpl(null, "fragment")); + node.setFragments(fragments); + assertSame(fragments, node.getFragments()); + } + + /** + * {@link ClassCoverageImpl#applyFragment(SourceNodeImpl)} + */ + @Test + public void testApplyFragment() { + // uncovered + final MethodCoverageImpl m = new MethodCoverageImpl("foo", "()V", null); + m.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42); + m.incrementMethodCounter(); + node.addMethod(m); + // covered + final SourceNodeImpl fragment = new SourceNodeImpl(null, "Sample"); + fragment.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, + 42); + node.applyFragment(fragment); + + assertEquals(CounterImpl.COUNTER_0_1, node.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getLineCounter()); + assertEquals(CounterImpl.COUNTER_0_0, node.getBranchCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getComplexityCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getMethodCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getClassCounter()); + LineImpl line = node.getLine(42); + assertEquals(CounterImpl.COUNTER_0_1, line.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_0, line.getBranchCounter()); + + assertEquals(CounterImpl.COUNTER_0_1, m.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_1, m.getLineCounter()); + assertEquals(CounterImpl.COUNTER_0_0, m.getBranchCounter()); + assertEquals(CounterImpl.COUNTER_0_1, m.getMethodCounter()); + line = m.getLine(42); + assertEquals(CounterImpl.COUNTER_0_1, line.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_0, line.getBranchCounter()); + } + private MethodCoverageImpl createMethod(boolean covered) { final MethodCoverageImpl m = new MethodCoverageImpl("sample", "()V", null); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java index 2ac2b2d998..cb80ef8b2a 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java @@ -13,6 +13,8 @@ package org.jacoco.core.internal.analysis; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.jacoco.core.analysis.ICoverageNode; import org.junit.Test; @@ -136,4 +138,57 @@ public void testIncrementComplexity8() { assertEquals(CounterImpl.getInstance(0, 2), node.getComplexityCounter()); } + + /** + * {@link MethodCoverageImpl#applyFragment(SourceNodeImpl)} + */ + @Test + public void testApplyFragment() { + // uncovered + MethodCoverageImpl node = new MethodCoverageImpl("sample", "()V", null); + node.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42); + node.incrementMethodCounter(); + // covered + final SourceNodeImpl fragment = new SourceNodeImpl(null, "fragment"); + fragment.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, + 42); + assertTrue(node.applyFragment(fragment)); + + assertEquals(CounterImpl.COUNTER_0_1, node.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getLineCounter()); + assertEquals(CounterImpl.COUNTER_0_0, node.getBranchCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getComplexityCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getMethodCounter()); + final LineImpl line = node.getLine(42); + assertEquals(CounterImpl.COUNTER_0_1, line.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_0, line.getBranchCounter()); + } + + /** + * {@link MethodCoverageImpl#applyFragment(SourceNodeImpl)} + */ + @Test + public void testApplyFragment2() { + // uncovered + MethodCoverageImpl node = new MethodCoverageImpl("sample", "()V", null); + node.increment(CounterImpl.COUNTER_1_0, CounterImpl.getInstance(2, 0), + 42); + node.incrementMethodCounter(); + // covered unrelated + final SourceNodeImpl fragment = new SourceNodeImpl(null, "fragment"); + fragment.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, + 13); + assertFalse(node.applyFragment(fragment)); + // should not change + assertEquals(CounterImpl.COUNTER_1_0, node.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_1_0, node.getLineCounter()); + assertEquals(CounterImpl.getInstance(2, 0), node.getBranchCounter()); + assertEquals(CounterImpl.getInstance(2, 0), + node.getComplexityCounter()); + assertEquals(CounterImpl.COUNTER_1_0, node.getMethodCounter()); + final LineImpl line = node.getLine(42); + assertEquals(CounterImpl.COUNTER_1_0, line.getInstructionCounter()); + assertEquals(CounterImpl.getInstance(2, 0), line.getBranchCounter()); + } + } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java index 9f82bf6f29..d530ccf897 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java @@ -13,6 +13,7 @@ package org.jacoco.core.internal.analysis; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.jacoco.core.analysis.ICoverageNode.ElementType; import org.jacoco.core.analysis.ISourceNode; @@ -223,4 +224,29 @@ public void testIncrementChildWithLines() { assertEquals(CounterImpl.getInstance(0, 1), node.getLineCounter()); } + /** + * {@link SourceNodeImpl#applyFragment(SourceNodeImpl)} + */ + @Test + public void testApplyFragment() { + // uncovered + final SourceNodeImpl node = new SourceNodeImpl(ElementType.CLASS, + "Foo"); + node.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_1_0, 42); + // covered + final SourceNodeImpl fragment = new SourceNodeImpl(null, "fragment"); + fragment.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, + 42); + + assertTrue(node.applyFragment(fragment)); + + assertEquals(CounterImpl.COUNTER_0_1, node.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_1, node.getLineCounter()); + assertEquals(CounterImpl.COUNTER_0_0, node.getBranchCounter()); + assertEquals(CounterImpl.COUNTER_0_0, node.getComplexityCounter()); + final LineImpl line = node.getLine(42); + assertEquals(CounterImpl.COUNTER_0_1, line.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_0, line.getBranchCounter()); + } + } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java index 33ecf84d62..f0b01765de 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java @@ -98,4 +98,31 @@ public void testWithLinesForKotlinNoDebug() { assertIgnored(); } + /** + *
    +	 * inline fun f() {
    +	 * }
    +	 * 
    + */ + @Test + public void should_filter_instructions_without_line_numbers() { + context.sourceFileName = "Example.kt"; + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "f", "()V", null, null); + m.visitInsn(Opcodes.ICONST_0); + final Range range1 = new Range(m.instructions.getLast(), + m.instructions.getLast()); + m.visitVarInsn(Opcodes.ISTORE, 1); + final Range range2 = new Range(m.instructions.getLast(), + m.instructions.getLast()); + m.visitLineNumber(1, new Label()); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(range1, range2); + } + } 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 89423ee1fa..50ccd23e15 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 @@ -171,7 +171,7 @@ public void last_line_in_coverage_data_should_be_less_or_equal_to_number_of_line } @Test - public void all_missed_instructions_should_have_line_number() { + public final void all_missed_instructions_should_have_line_number() { CounterImpl c = CounterImpl.COUNTER_0_0; for (Line line : source.getLines()) { c = c.increment(line.getCoverage().getInstructionCounter()); @@ -183,7 +183,7 @@ public void all_missed_instructions_should_have_line_number() { } @Test - public void all_branches_should_have_line_number() { + public final void all_branches_should_have_line_number() { CounterImpl c = CounterImpl.COUNTER_0_0; for (Line line : source.getLines()) { c = c.increment(line.getCoverage().getBranchCounter()); diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java index 4f9a9050d9..cfd6a13c88 100644 --- a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java +++ b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java @@ -19,7 +19,9 @@ import java.util.Map; import org.jacoco.core.internal.analysis.BundleCoverageImpl; +import org.jacoco.core.internal.analysis.ClassCoverageImpl; import org.jacoco.core.internal.analysis.SourceFileCoverageImpl; +import org.jacoco.core.internal.analysis.SourceNodeImpl; /** * Builder for hierarchical {@link ICoverageNode} structures from single @@ -39,7 +41,7 @@ public class CoverageBuilder implements ICoverageVisitor { private final Map classes; - private final Map sourcefiles; + private Map sourcefiles; /** * Create a new builder. @@ -56,6 +58,7 @@ public CoverageBuilder() { * @return all class nodes */ public Collection getClasses() { + build(); return Collections.unmodifiableCollection(classes.values()); } @@ -65,6 +68,7 @@ public Collection getClasses() { * @return all source file nodes */ public Collection getSourceFiles() { + build(); return Collections.unmodifiableCollection(sourcefiles.values()); } @@ -76,6 +80,7 @@ public Collection getSourceFiles() { * @return bundle containing all classes and source files */ public IBundleCoverage getBundle(final String name) { + build(); return new BundleCoverageImpl(name, classes.values(), sourcefiles.values()); } @@ -96,9 +101,35 @@ public Collection getNoMatchClasses() { return result; } + private void build() { + if (sourcefiles != null) { + return; + } + this.sourcefiles = new HashMap(); + for (final IClassCoverage c : classes.values()) { + for (final SourceNodeImpl fragment : ((ClassCoverageImpl) c) + .getFragments()) { + final SourceNodeImpl classCoverage = (SourceNodeImpl) classes + .get(fragment.getName()); + if (classCoverage != null) { + classCoverage.applyFragment(fragment); + } + } + } + for (final IClassCoverage coverage : classes.values()) { + final String source = coverage.getSourceFileName(); + if (source != null) { + final SourceFileCoverageImpl sourceFile = getSourceFile(source, + coverage.getPackageName()); + sourceFile.increment(coverage); + } + } + } + // === ICoverageVisitor === public void visitCoverage(final IClassCoverage coverage) { + sourcefiles = null; final String name = coverage.getName(); final IClassCoverage dup = classes.put(name, coverage); if (dup != null) { @@ -106,13 +137,6 @@ public void visitCoverage(final IClassCoverage coverage) { throw new IllegalStateException( "Can't add different class with same name: " + name); } - } else { - final String source = coverage.getSourceFileName(); - if (source != null) { - final SourceFileCoverageImpl sourceFile = getSourceFile(source, - coverage.getPackageName()); - sourceFile.increment(coverage); - } } } 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 0ca43a9bf7..d2268c5507 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java @@ -12,12 +12,17 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis; +import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; 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; import org.jacoco.core.internal.instr.InstrSupport; @@ -25,6 +30,7 @@ import org.objectweb.asm.Attribute; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.MethodNode; /** @@ -42,6 +48,8 @@ public class ClassAnalyzer extends ClassProbesVisitor private final Set classAttributes = new HashSet(); private String sourceDebugExtension; + private KotlinSMAP smap; + private final HashMap fragments = new HashMap(); private final IFilter filter; @@ -114,8 +122,13 @@ public void accept(final MethodNode methodNode, private void addMethodCoverage(final String name, final String desc, final String signature, final InstructionsBuilder icc, final MethodNode methodNode) { + + final Map instructions = icc + .getInstructions(); + calculateFragments(instructions); + final MethodCoverageCalculator mcc = new MethodCoverageCalculator( - icc.getInstructions()); + instructions); filter.filter(methodNode, this, mcc); final MethodCoverageImpl mc = new MethodCoverageImpl(name, desc, @@ -129,6 +142,41 @@ private void addMethodCoverage(final String name, final String desc, } + private void calculateFragments( + final Map instructions) { + if (sourceDebugExtension == null + || !KotlinGeneratedFilter.isKotlinClass(this)) { + return; + } + if (smap == null) { + // Note that visitSource is invoked before visitAnnotation, + // that's why parsing is done here + smap = new KotlinSMAP(getSourceFileName(), sourceDebugExtension); + } + for (final KotlinSMAP.Mapping mapping : smap.mappings()) { + if (coverage.getName().equals(mapping.inputClassName()) + && mapping.inputStartLine() == mapping.outputStartLine()) { + continue; + } + SourceNodeImpl fragment = fragments.get(mapping.inputClassName()); + if (fragment == null) { + fragment = new SourceNodeImpl(null, mapping.inputClassName()); + fragments.put(mapping.inputClassName(), fragment); + } + final int mappingOutputEndLine = mapping.outputStartLine() + + mapping.repeatCount() - 1; + for (Instruction instruction : instructions.values()) { + if (mapping.outputStartLine() <= instruction.getLine() + && instruction.getLine() <= mappingOutputEndLine) { + final int originalLine = mapping.inputStartLine() + + instruction.getLine() - mapping.outputStartLine(); + fragment.increment(instruction.getInstructionCounter(), + CounterImpl.COUNTER_0_0, originalLine); + } + } + } + } + @Override public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { @@ -141,6 +189,14 @@ public void visitTotalProbeCount(final int count) { // nothing to do } + @Override + public void visitEnd() { + if (!fragments.isEmpty()) { + coverage.setFragments(Arrays + .asList(fragments.values().toArray(new SourceNodeImpl[0]))); + } + } + // IFilterContext implementation public String getClassName() { 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 be90d9b674..f4dc7e8870 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 @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import org.jacoco.core.analysis.IClassCoverage; import org.jacoco.core.analysis.IMethodCoverage; @@ -32,6 +33,8 @@ public class ClassCoverageImpl extends SourceNodeImpl private String[] interfaces; private String sourceFileName; + private Collection fragments = Collections.emptyList(); + /** * Creates a class coverage data object with the given parameters. * @@ -109,6 +112,45 @@ public void setSourceFileName(final String sourceFileName) { this.sourceFileName = sourceFileName; } + /** + * @return fragments stored in this class + */ + public Collection getFragments() { + return fragments; + } + + public void setFragments(final Collection fragments) { + this.fragments = fragments; + } + + @Override + public boolean applyFragment(final SourceNodeImpl fragment) { + super.applyFragment(fragment); + for (final IMethodCoverage methodCoverage : methods) { + final int mm = methodCoverage.getMethodCounter().getMissedCount(); + final int cm = methodCoverage.getMethodCounter().getCoveredCount(); + final int mc = methodCoverage.getComplexityCounter() + .getMissedCount(); + final int cc = methodCoverage.getComplexityCounter() + .getCoveredCount(); + if (((MethodCoverageImpl) methodCoverage).applyFragment(fragment)) { + methodCounter = methodCounter.increment( + methodCoverage.getMethodCounter().getMissedCount() - mm, + methodCoverage.getMethodCounter().getCoveredCount() + - cm); + complexityCounter = complexityCounter.increment( + methodCoverage.getComplexityCounter().getMissedCount() + - mc, + methodCoverage.getComplexityCounter().getCoveredCount() + - cc); + } + } + classCounter = methodCounter.getCoveredCount() > 0 + ? CounterImpl.COUNTER_0_1 + : CounterImpl.COUNTER_1_0; + return true; + } + // === IClassCoverage implementation === public long getId() { diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java index e6ee3283cf..25c7da1835 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java @@ -66,6 +66,18 @@ public void incrementMethodCounter() { this.complexityCounter = this.complexityCounter.increment(base); } + @Override + public boolean applyFragment(final SourceNodeImpl fragment) { + final boolean applied = super.applyFragment(fragment); + if (applied) { + methodCounter = instructionCounter.getCoveredCount() == 0 + ? CounterImpl.COUNTER_1_0 + : CounterImpl.COUNTER_0_1; + complexityCounter = methodCounter; + } + return applied; + } + // === IMethodCoverage implementation === public String getDesc() { 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 48fd48bd96..bab8b9edfd 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 @@ -41,6 +41,41 @@ public SourceNodeImpl(final ElementType elementType, final String name) { offset = UNKNOWN_LINE; } + /** + * @return true if fragment contains lines of this node + */ + public boolean applyFragment(final SourceNodeImpl fragment) { + boolean applied = false; + for (int line = getFirstLine(); line <= getLastLine(); line++) { + final ILine fragmentLine = fragment.getLine(line); + if (fragmentLine.equals(LineImpl.EMPTY)) { + continue; + } + final LineImpl l = getLine(line); + final CounterImpl counter; + if (l.getInstructionCounter().getCoveredCount() > 0 || fragmentLine + .getInstructionCounter().getCoveredCount() > 0) { + counter = CounterImpl.COUNTER_0_1; + } else { + counter = CounterImpl.COUNTER_1_0; + } + lines[line - offset] = LineImpl.EMPTY; + if (l.instructions.covered > 0) { + lineCounter = lineCounter.increment(0, -1); + } else if (l.instructions.missed > 0) { + lineCounter = lineCounter.increment(-1, 0); + } + incrementLine(counter, CounterImpl.COUNTER_0_0, line); + instructionCounter = instructionCounter.increment( + counter.missed - l.instructions.missed, + counter.covered - l.instructions.covered); + branchCounter = branchCounter.increment(-l.branches.missed, + -l.branches.covered); + applied = true; + } + return applied; + } + /** * Make sure that the internal buffer can keep lines from first to last. * While the buffer is also incremented automatically, this method allows 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 ed3063f566..2bc32b1a21 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,7 +24,7 @@ public class KotlinGeneratedFilter implements IFilter { static final String KOTLIN_METADATA_DESC = "Lkotlin/Metadata;"; - static boolean isKotlinClass(final IFilterContext context) { + public static boolean isKotlinClass(final IFilterContext context) { return context.getClassAnnotations().contains(KOTLIN_METADATA_DESC); } @@ -42,6 +42,12 @@ public void filter(final MethodNode methodNode, } if (hasLineNumber(methodNode)) { + for (final AbstractInsnNode i : methodNode.instructions) { + if (AbstractInsnNode.LINE == i.getType()) { + break; + } + output.ignore(i, i); + } return; } 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 8062199ae4..aa7a8d7b12 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 @@ -24,7 +24,7 @@ /** * Parsed representation of SourceDebugExtension attribute. */ -final class KotlinSMAP { +public final class KotlinSMAP { public static final class Mapping { private final String inputClassName; diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 27af4034e4..4a2ec80bd1 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,6 +22,8 @@

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    New Features

      +
    • Calculation of line coverage for Kotlin inline functions + (GitHub #1670).
    • Experimental support for Java 24 class files (GitHub #1631).
    • Part of bytecode generated by the Kotlin Compose compiler plugin is From 1988ec3c808b0d9e616741bba87846c867f2fa63 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 7 Sep 2024 00:33:24 +0200 Subject: [PATCH 088/255] Add validation test for synthetic accessor methods in Kotlin (#1675) --- .../kotlin/KotlinSyntheticAccessorsTest.java | 54 +++++++++++++++++++ .../targets/KotlinSyntheticAccessorsTarget.kt | 45 ++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSyntheticAccessorsTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSyntheticAccessorsTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSyntheticAccessorsTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSyntheticAccessorsTest.java new file mode 100644 index 0000000000..01543fb23d --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSyntheticAccessorsTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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 static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; + +import org.jacoco.core.test.validation.ValidationTestBase; +import org.jacoco.core.test.validation.kotlin.targets.KotlinSyntheticAccessorsTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinSyntheticAccessorsTarget}. + */ +public class KotlinSyntheticAccessorsTest extends ValidationTestBase { + + public KotlinSyntheticAccessorsTest() { + super(KotlinSyntheticAccessorsTarget.class); + } + + @Test + public void compiler_should_generate_synthetic_accessors() { + final HashSet names = new HashSet(); + for (final Method method : KotlinSyntheticAccessorsTarget.Outer.class + .getDeclaredMethods()) { + if (method.isSynthetic()) { + names.add(method.getName()); + } + } + + assertEquals(new HashSet( + Arrays.asList("access$getX", "access$getX$p", "access$setX$p")), + names); + } + + @Test + public void test_method_count() { + assertMethodCount(/* main + 2 in Outer + 2 in Inner */ 5); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSyntheticAccessorsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSyntheticAccessorsTarget.kt new file mode 100644 index 0000000000..36a418ace3 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSyntheticAccessorsTarget.kt @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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 synthetic accessor methods. + */ +object KotlinSyntheticAccessorsTarget { + + class Outer { // assertFullyCovered() + private var x = 42 + + private fun getX(): Int { + return x + } + + inner class Inner { // assertFullyCovered() + /** + * Access to private field and function of outer class causes creation of synthetic methods in it. + * Those methods refer to the line of outer class definition. + */ + @Suppress("unused") + fun accessOuter() { + x += 1 // assertNotCovered() + getX() + } + } + } + + @JvmStatic + fun main(args: Array) { + Outer().Inner() + } + +} From 44b4e5aeb3aabd370e9632074c2a426455aeb482 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 7 Sep 2024 02:50:31 +0200 Subject: [PATCH 089/255] Nested classes should be static when they do not use reference to outer (#1688) --- jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java | 4 ++-- org.jacoco.ant/src/org/jacoco/ant/ReportTask.java | 2 +- .../analysis/filter/TryWithResourcesJavac11Filter.java | 2 +- .../org/jacoco/report/internal/html/page/ClassPageTest.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java b/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java index 46d09c99ac..bb42efa2fc 100644 --- a/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java +++ b/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java @@ -195,7 +195,7 @@ private void logBundleInfo(final IBundleCoverage bundle, } } - private class NoSourceLocator implements ISourceFileLocator { + private static class NoSourceLocator implements ISourceFileLocator { public Reader getSourceFile(final String packageName, final String fileName) { @@ -207,7 +207,7 @@ public int getTabWidth() { } } - private class SourceFileCollection implements ISourceFileLocator { + private static class SourceFileCollection implements ISourceFileLocator { private final List sourceRoots; private final String encoding; diff --git a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java index cbcc685810..24051ce7af 100644 --- a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java +++ b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java @@ -152,7 +152,7 @@ public SourceFilesElement createSourcefiles() { /** * Interface for child elements that define formatters. */ - private abstract class FormatterElement { + private abstract static class FormatterElement { abstract IReportVisitor createVisitor() throws IOException; 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 120c964289..ddd24c2a3b 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 @@ -60,7 +60,7 @@ public void filter(final MethodNode methodNode, * null check for resource is omitted when it is initialized * using new */ - private class Matcher extends AbstractMatcher { + private static class Matcher extends AbstractMatcher { private boolean withNullCheck; private String expectedOwner; diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java index af4e6be015..6aee733203 100644 --- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java +++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java @@ -148,7 +148,7 @@ public void should_generate_message_when_class_id_mismatch() support.findStr(doc, "/html/body/p[1]")); } - private class SourceLink implements ILinkable { + private static class SourceLink implements ILinkable { public String getLink(final ReportOutputFolder base) { return "Source.java.html"; From 58b3e65efd4237607361f1643cd485945a508262 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:50:27 +0200 Subject: [PATCH 090/255] SyntheticFilter should filter out only synthetic accessors in Kotlin classes (#1700) --- .../kotlin/KotlinInlineReifiedTest.java | 52 ++++++++++++++++++ .../kotlin/KotlinJvmSyntheticTest.java | 52 ++++++++++++++++++ .../targets/KotlinInlineReifiedTarget.kt | 32 +++++++++++ .../targets/KotlinJvmSyntheticTarget.kt | 32 +++++++++++ .../analysis/filter/SyntheticFilterTest.java | 53 +++++++++++++++++++ .../filter/KotlinCoroutineFilter.java | 12 ----- .../filter/KotlinDefaultArgumentsFilter.java | 6 ++- .../analysis/filter/SyntheticFilter.java | 13 +---- org.jacoco.doc/docroot/doc/changes.html | 8 ++- 9 files changed, 233 insertions(+), 27 deletions(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineReifiedTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmSyntheticTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineReifiedTarget.kt create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmSyntheticTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineReifiedTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineReifiedTest.java new file mode 100644 index 0000000000..b84bb480d2 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineReifiedTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; + +import org.jacoco.core.test.validation.ValidationTestBase; +import org.jacoco.core.test.validation.kotlin.targets.KotlinInlineReifiedTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinInlineReifiedTarget}. + */ +public class KotlinInlineReifiedTest extends ValidationTestBase { + + public KotlinInlineReifiedTest() { + super(KotlinInlineReifiedTarget.class); + } + + @Test + public void compiler_should_generate_synthetic_method() { + final HashSet names = new HashSet(); + for (final Method method : KotlinInlineReifiedTarget.class + .getDeclaredMethods()) { + if (method.isSynthetic()) { + names.add(method.getName()); + } + } + + assertEquals(Collections.singleton("example"), names); + } + + @Test + public void test_method_count() { + assertMethodCount(2); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmSyntheticTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmSyntheticTest.java new file mode 100644 index 0000000000..4847d6a614 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmSyntheticTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; + +import org.jacoco.core.test.validation.ValidationTestBase; +import org.jacoco.core.test.validation.kotlin.targets.KotlinJvmSyntheticTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinJvmSyntheticTarget}. + */ +public class KotlinJvmSyntheticTest extends ValidationTestBase { + + public KotlinJvmSyntheticTest() { + super(KotlinJvmSyntheticTarget.class); + } + + @Test + public void compiler_should_generate_synthetic_method() { + final HashSet names = new HashSet(); + for (final Method method : KotlinJvmSyntheticTarget.class + .getDeclaredMethods()) { + if (method.isSynthetic()) { + names.add(method.getName()); + } + } + + assertEquals(Collections.singleton("example"), names); + } + + @Test + public void test_method_count() { + assertMethodCount(2); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineReifiedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineReifiedTarget.kt new file mode 100644 index 0000000000..3ca4a2899b --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineReifiedTarget.kt @@ -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.targets + +import org.jacoco.core.test.validation.targets.Stubs.nop + +/** + * Test target containing `inline` function with + * [`reified` type parameter](https://kotlinlang.org/docs/inline-functions.html#reified-type-parameters). + */ +object KotlinInlineReifiedTarget { + + private inline fun example() { // assertEmpty() + nop(T::class) // assertFullyCovered() + } // assertFullyCovered() + + @JvmStatic + fun main(args: Array) { + example() + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmSyntheticTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmSyntheticTarget.kt new file mode 100644 index 0000000000..4f434a2eb5 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmSyntheticTarget.kt @@ -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.targets + +import org.jacoco.core.test.validation.targets.Stubs.nop + +/** + * Test target containing [JvmSynthetic] function. + */ +object KotlinJvmSyntheticTarget { + + @JvmSynthetic + private fun example() { // assertEmpty() + nop() // assertFullyCovered() + } // assertFullyCovered() + + @JvmStatic + fun main(args: Array) { + example() + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java index 81942aa480..d0cd63f417 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java @@ -57,6 +57,59 @@ public void testLambda() { assertIgnored(); } + /** + *
      +	 * @JvmSynthetic
      +	 * fun example() {
      +	 * }
      +	 * 
      + * + * @see #should_filter_synthetic_accessor_methods_in_Kotlin_classes() + */ + @Test + public void should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "example", "()V", null, null); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + + /** + *
      +	 * class Outer {
      +	 *   private var x = 42
      +	 *
      +	 *   inner class Inner {
      +	 *     fun example() {
      +	 *       x += 1
      +	 *     }
      +	 *   }
      +	 * }
      +	 * 
      + * + * @see #should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() + */ + @Test + public void should_filter_synthetic_accessor_methods_in_Kotlin_classes() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "access$getX$p", "(Outer;)I", null, + null); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "Outer", "x", "I"); + m.visitInsn(Opcodes.IRETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + @Test public void should_filter_synthetic_method_with_prefix_anonfun_in_non_Scala_classes() { final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 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 6dd47fd413..64a2016175 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 @@ -16,7 +16,6 @@ import java.util.List; import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LdcInsnNode; @@ -29,17 +28,6 @@ */ public final class KotlinCoroutineFilter implements IFilter { - static boolean isImplementationOfSuspendFunction( - final MethodNode methodNode) { - if (methodNode.name.startsWith("access$")) { - return false; - } - final Type methodType = Type.getMethodType(methodNode.desc); - final int lastArgument = methodType.getArgumentTypes().length - 1; - return lastArgument >= 0 && "kotlin.coroutines.Continuation".equals( - methodType.getArgumentTypes()[lastArgument].getClassName()); - } - 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/KotlinDefaultArgumentsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java index 8ea1603b0a..978dd29750 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 @@ -52,11 +52,13 @@ */ public final class KotlinDefaultArgumentsFilter implements IFilter { - static boolean isDefaultArgumentsMethod(final MethodNode methodNode) { + private static boolean isDefaultArgumentsMethod( + final MethodNode methodNode) { return methodNode.name.endsWith("$default"); } - static boolean isDefaultArgumentsConstructor(final MethodNode methodNode) { + private static boolean isDefaultArgumentsConstructor( + final MethodNode methodNode) { if (!"".equals(methodNode.name)) { return false; } 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 8a2dfd4890..55e35a621c 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 @@ -42,18 +42,7 @@ public void filter(final MethodNode methodNode, } if (KotlinGeneratedFilter.isKotlinClass(context)) { - if (KotlinDefaultArgumentsFilter - .isDefaultArgumentsMethod(methodNode)) { - return; - } - - if (KotlinDefaultArgumentsFilter - .isDefaultArgumentsConstructor(methodNode)) { - return; - } - - if (KotlinCoroutineFilter - .isImplementationOfSuspendFunction(methodNode)) { + if (!methodNode.name.startsWith("access$")) { return; } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 4a2ec80bd1..faf85507f1 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,8 +22,14 @@

      Snapshot Build @qualified.bundle.version@ (@build.date@)

      New Features

        -
      • 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 091/255] 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 092/255] 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 093/255] 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.9 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 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:

        -  mvn clean verify
        +  ../mvnw clean verify
         

        @@ -48,7 +48,7 @@

        Running the Build

        -  ./jacoco/target/jacoco-x.y.z.qualifier.zip
        +  ../jacoco/target/jacoco-x.y.z.qualifier.zip
         
        @@ -59,7 +59,7 @@

        Running Quick Build without Tests

        -  mvn clean verify -DskipTests
        +  ../mvnw clean verify -DskipTests
         
        @@ -305,7 +305,7 @@

        Compilation and testing with different JDKs

        -  mvn clean verify -Djdk.version=10 -Dbytecode.version=9
        +  ../mvnw clean verify -Djdk.version=10 -Dbytecode.version=9
         

        @@ -313,7 +313,7 @@

        Compilation and testing with different JDKs

        -  mvn clean verify -Decj
        +  ../mvnw clean verify -Decj
         

        @@ -321,27 +321,27 @@

        Compilation and testing with different JDKs

          -
        • mvn clean verify -Djdk.version=5 -Dbytecode.version=5
        • -
        • mvn clean verify -Djdk.version=6 -Dbytecode.version=6
        • -
        • mvn clean verify -Djdk.version=7 -Dbytecode.version=7
        • -
        • mvn clean verify -Djdk.version=8 -Dbytecode.version=8
        • -
        • mvn clean verify -Djdk.version=9 -Dbytecode.version=9
        • -
        • mvn clean verify -Djdk.version=10 -Dbytecode.version=10
        • -
        • mvn clean verify -Djdk.version=11 -Dbytecode.version=11
        • -
        • mvn clean verify -Djdk.version=11 -Dbytecode.version=11 -Decj
        • -
        • mvn clean verify -Djdk.version=12 -Dbytecode.version=12
        • -
        • mvn clean verify -Djdk.version=13 -Dbytecode.version=13
        • -
        • mvn clean verify -Djdk.version=14 -Dbytecode.version=14
        • -
        • mvn clean verify -Djdk.version=15 -Dbytecode.version=15
        • -
        • mvn clean verify -Djdk.version=16 -Dbytecode.version=16
        • -
        • mvn clean verify -Djdk.version=17 -Dbytecode.version=17
        • -
        • mvn clean verify -Djdk.version=17 -Dbytecode.version=17 -Decj
        • -
        • mvn clean verify -Djdk.version=18 -Dbytecode.version=18
        • -
        • mvn clean verify -Djdk.version=19 -Dbytecode.version=19
        • -
        • mvn clean verify -Djdk.version=20 -Dbytecode.version=20
        • -
        • mvn clean verify -Djdk.version=21 -Dbytecode.version=21
        • -
        • mvn clean verify -Djdk.version=21 -Dbytecode.version=21 -Decj
        • -
        • mvn clean verify -Djdk.version=22 -Dbytecode.version=22
        • +
        • ../mvnw clean verify -Djdk.version=5 -Dbytecode.version=5
        • +
        • ../mvnw clean verify -Djdk.version=6 -Dbytecode.version=6
        • +
        • ../mvnw clean verify -Djdk.version=7 -Dbytecode.version=7
        • +
        • ../mvnw clean verify -Djdk.version=8 -Dbytecode.version=8
        • +
        • ../mvnw clean verify -Djdk.version=9 -Dbytecode.version=9
        • +
        • ../mvnw clean verify -Djdk.version=10 -Dbytecode.version=10
        • +
        • ../mvnw clean verify -Djdk.version=11 -Dbytecode.version=11
        • +
        • ../mvnw clean verify -Djdk.version=11 -Dbytecode.version=11 -Decj
        • +
        • ../mvnw clean verify -Djdk.version=12 -Dbytecode.version=12
        • +
        • ../mvnw clean verify -Djdk.version=13 -Dbytecode.version=13
        • +
        • ../mvnw clean verify -Djdk.version=14 -Dbytecode.version=14
        • +
        • ../mvnw clean verify -Djdk.version=15 -Dbytecode.version=15
        • +
        • ../mvnw clean verify -Djdk.version=16 -Dbytecode.version=16
        • +
        • ../mvnw clean verify -Djdk.version=17 -Dbytecode.version=17
        • +
        • ../mvnw clean verify -Djdk.version=17 -Dbytecode.version=17 -Decj
        • +
        • ../mvnw clean verify -Djdk.version=18 -Dbytecode.version=18
        • +
        • ../mvnw clean verify -Djdk.version=19 -Dbytecode.version=19
        • +
        • ../mvnw clean verify -Djdk.version=20 -Dbytecode.version=20
        • +
        • ../mvnw clean verify -Djdk.version=21 -Dbytecode.version=21
        • +
        • ../mvnw clean verify -Djdk.version=21 -Dbytecode.version=21 -Decj
        • +
        • ../mvnw clean verify -Djdk.version=22 -Dbytecode.version=22
        diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index faf85507f1..564a417cfd 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -57,8 +57,10 @@

        Fixed bugs

        Non-functional Changes

          -
        • JaCoCo build now requires at least Maven 3.6.3 - (GitHub #1681).
        • +
        • JaCoCo build now uses Maven Wrapper and requires at least Maven 3.9.9 + (GitHub #1708, + #1707, + #1681).

        Release 0.8.12 (2024/03/31)

        diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html index 1d827fe4f6..140a5e9f01 100644 --- a/org.jacoco.doc/docroot/doc/environment.html +++ b/org.jacoco.doc/docroot/doc/environment.html @@ -76,7 +76,7 @@

        Build

        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.

        From 27427bd091e14fca210bed9953711103f5ce7cad Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:32:35 +0200 Subject: [PATCH 094/255] Enable checksum verification of Maven distribution (#1709) --- .mvn/wrapper/maven-wrapper.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index d58dfb70ba..fe9deed0b0 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -17,3 +17,4 @@ wrapperVersion=3.3.2 distributionType=only-script distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip +distributionSha256Sum=4ec3f26fb1a692473aea0235c300bd20f0f9fe741947c82c1234cefd76ac3a3c From 2b375134c541731816dea07e12ce7e720661d5b5 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:34:09 +0200 Subject: [PATCH 095/255] Add configuration for Dependabot to simplify updates of Maven plugins (#1701) --- .github/dependabot.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0cdb098373..f49500be46 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,7 +8,26 @@ updates: - "dependencies" - "component: build" - package-ecosystem: "maven" - directory: "/" + directory: "/org.jacoco.build" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "component: build" + allow: + - dependency-name: "org.apache.maven.plugins:*" + - dependency-name: "org.codehaus.mojo:*" + - dependency-name: "com.diffplug.spotless:*" + - dependency-name: "org.sonarsource.scanner.maven:*" + 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" + # Requires tests to be executed with Java 6: + - dependency-name: "org.apache.maven.plugins:maven-surefire-plugin" + versions: ">=2.20.0" + - package-ecosystem: "maven" + directory: "/org.jacoco.core" schedule: interval: "daily" labels: From 2f996967195423ac77390c6d43253bfc0bcdd40e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:30:54 +0200 Subject: [PATCH 096/255] Upgrade exec-maven-plugin to 3.4.1 (#1711) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.1.0 to 3.4.1. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/exec-maven-plugin-3.1.0...3.4.1) --- 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 6a24dc0a69..50ba48cfc6 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -433,7 +433,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.4.1 From c185535411eda2e5974fe493a25d3998e6f1d35a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:27:50 +0000 Subject: [PATCH 097/255] Upgrade maven-toolchains-plugin to 3.2.0 (#1712) Bumps [org.apache.maven.plugins:maven-toolchains-plugin](https://github.com/apache/maven-toolchains-plugin) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/apache/maven-toolchains-plugin/releases) - [Commits](https://github.com/apache/maven-toolchains-plugin/compare/maven-toolchains-plugin-3.1.0...maven-toolchains-plugin-3.2.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-toolchains-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 50ba48cfc6..8bb3b1c24e 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -407,7 +407,7 @@ org.apache.maven.plugins maven-toolchains-plugin - 3.1.0 + 3.2.0 From a6521f1850fc494d93b630424a575610ab397493 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:34:00 +0000 Subject: [PATCH 098/255] Upgrade maven-clean-plugin to 3.4.0 (#1713) Bumps [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) from 3.2.0 to 3.4.0. - [Release notes](https://github.com/apache/maven-clean-plugin/releases) - [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.2.0...maven-clean-plugin-3.4.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-clean-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 8bb3b1c24e..0274c17461 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -307,7 +307,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.2.0 + 3.4.0 org.apache.maven.plugins From d28300a5bc2bfca432b24bb660a0ceb1e1aa45d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:03:21 +0000 Subject: [PATCH 099/255] Upgrade build-helper-maven-plugin to 3.6.0 (#1710) Bumps [org.codehaus.mojo:build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) from 3.4.0 to 3.6.0. - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/3.4.0...3.6.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:build-helper-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 0274c17461..012ccd702d 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -418,7 +418,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.6.0 org.codehaus.mojo From ae002e534ed9ec0ab0de17091e4f77bbe66b7346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:15:10 +0000 Subject: [PATCH 100/255] Upgrade buildnumber-maven-plugin to 3.2.1 (#1714) Bumps [org.codehaus.mojo:buildnumber-maven-plugin](https://github.com/mojohaus/buildnumber-maven-plugin) from 3.1.0 to 3.2.1. - [Release notes](https://github.com/mojohaus/buildnumber-maven-plugin/releases) - [Commits](https://github.com/mojohaus/buildnumber-maven-plugin/compare/3.1.0...3.2.1) --- updated-dependencies: - dependency-name: org.codehaus.mojo:buildnumber-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 012ccd702d..c8f8323be0 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -423,7 +423,7 @@ org.codehaus.mojo buildnumber-maven-plugin - 3.1.0 + 3.2.1 org.codehaus.mojo From 9f2b0dd79f5ce74f6a5c327413d68c759bc83065 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:40:14 +0200 Subject: [PATCH 101/255] Upgrade org.apache.maven.plugins:maven-dependency-plugin to 3.8.0 (#1718) Bumps [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) from 3.6.0 to 3.8.0. - [Release notes](https://github.com/apache/maven-dependency-plugin/releases) - [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.0...maven-dependency-plugin-3.8.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-dependency-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 c8f8323be0..00bf86dd69 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -317,7 +317,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.0 + 3.8.0 org.apache.maven.plugins From 2e63a8db9ce73661958a332b3f8055d3c2dfb28e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:04:42 +0200 Subject: [PATCH 102/255] Upgrade maven-assembly-plugin to 3.7.1 (#1715) Bumps [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.6.0 to 3.7.1. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.6.0...maven-assembly-plugin-3.7.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-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 00bf86dd69..f2103a5da4 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -302,7 +302,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 org.apache.maven.plugins From c277cd1a43fea8df96972fa00116a3c2286e9ca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:56:04 +0200 Subject: [PATCH 103/255] Upgrade maven-jar-plugin to 3.4.2 (#1716) Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.2. - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-jar-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 f2103a5da4..eb55ce5a35 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -347,7 +347,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 org.apache.maven.plugins From 013e4c6e15ab5976dab37d0a5a987a69cf07944e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:46:35 +0200 Subject: [PATCH 104/255] Upgrade maven-enforcer-plugin to 3.5.0 (#1720) Bumps [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/apache/maven-enforcer/releases) - [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.3.0...enforcer-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-enforcer-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 eb55ce5a35..8c9f2a1c4d 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -327,7 +327,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.3.0 + 3.5.0 org.apache.maven.plugins From 9cbd49769a18e11038869db153b242aef62ba93a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 19:10:08 +0000 Subject: [PATCH 105/255] Upgrade maven-shade-plugin to 3.6.0 (#1721) Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-shade-plugin/releases) - [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-shade-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> Co-authored-by: Evgeny Mandrikov --- org.jacoco.build/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 8c9f2a1c4d..23ebef2988 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -386,7 +386,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 org.apache.maven.plugins @@ -840,7 +840,7 @@ + 22 16 @@ -533,7 +533,7 @@ - + 22 16 From 91585a0eb39675200b8954d4bc9b2d428937a440 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:49:38 +0000 Subject: [PATCH 119/255] Upgrade maven-gpg-plugin to 3.2.7 (#1732) Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.6 to 3.2.7. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.6...maven-gpg-plugin-3.2.7) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-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 4510045fd8..a6dfe84cde 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -342,7 +342,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.6 + 3.2.7 org.apache.maven.plugins From 66a46287d9c1cb10ae6fec3f9499554642d6a40c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:40:17 +0200 Subject: [PATCH 120/255] Upgrade ASM to 9.7.1 (#1739) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Evgeny Mandrikov --- org.jacoco.build/licenses/{asm-9.7.html => asm-9.7.1.html} | 0 org.jacoco.build/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) rename org.jacoco.build/licenses/{asm-9.7.html => asm-9.7.1.html} (100%) diff --git a/org.jacoco.build/licenses/asm-9.7.html b/org.jacoco.build/licenses/asm-9.7.1.html similarity index 100% rename from org.jacoco.build/licenses/asm-9.7.html rename to org.jacoco.build/licenses/asm-9.7.1.html diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index a6dfe84cde..a870bd4b54 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -139,7 +139,7 @@ ${jvm.args} - 9.7 + 9.7.1 1.9.16 2.0.28 4.13.2 diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 564a417cfd..6b2e5f4297 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -61,6 +61,8 @@

        Non-functional Changes

        (GitHub #1708, #1707, #1681).
      • +
      • JaCoCo now depends on ASM 9.7.1 + (GitHub #1739).

      Release 0.8.12 (2024/03/31)

      From cb4b2138b49545814706c2cf5ec328940cf9b4d3 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:38:11 +0200 Subject: [PATCH 121/255] Happy birthday Java 23! (#1757) --- org.jacoco.doc/docroot/doc/build.html | 11 +++++++++++ org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/docroot/doc/environment.html | 2 +- org.jacoco.doc/docroot/doc/faq.html | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index f524bdbce4..3a304433a8 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -99,6 +99,7 @@

      Compilation and testing with different JDKs

      JDK 20 JDK 21 JDK 22 + JDK 23 @@ -122,6 +123,7 @@

      Compilation and testing with different JDKs

      21 21 + 21 org.jacoco.core.test.validation.java16 @@ -143,6 +145,7 @@

      Compilation and testing with different JDKs

      16 16 16 + 16 org.jacoco.core.test.validation.java14 @@ -164,6 +167,7 @@

      Compilation and testing with different JDKs

      14 14 14 + 14 org.jacoco.core.test.validation.java8 @@ -185,6 +189,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 org.jacoco.core.test.validation.java7 @@ -206,6 +211,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 org.jacoco.core.test.validation.groovy @@ -227,6 +233,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 org.jacoco.core.test.validation.kotlin @@ -248,6 +255,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 org.jacoco.core.test.validation.scala @@ -269,6 +277,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 all other modules @@ -290,6 +299,7 @@

      Compilation and testing with different JDKs

      8 8 8 + 8 @@ -342,6 +352,7 @@

      Compilation and testing with different JDKs

    • ../mvnw clean verify -Djdk.version=21 -Dbytecode.version=21
    • ../mvnw clean verify -Djdk.version=21 -Dbytecode.version=21 -Decj
    • ../mvnw clean verify -Djdk.version=22 -Dbytecode.version=22
    • +
    • ../mvnw clean verify -Djdk.version=23 -Dbytecode.version=23
    diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 6b2e5f4297..144fe37ec9 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,6 +22,8 @@

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    New Features

      +
    • 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.

      Build

      diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html index 54ba89885e..8dabc61b4b 100644 --- a/org.jacoco.doc/docroot/doc/faq.html +++ b/org.jacoco.doc/docroot/doc/faq.html @@ -45,7 +45,7 @@

      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 122/255] 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.plugins maven-javadoc-plugin - 3.10.0 + 3.10.1 true false 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 123/255] 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.plugins maven-compiler-plugin - 3.11.0 + + 3.12.1 org.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 124/255] 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.mojo exec-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 125/255] 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 126/255] 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 127/255] 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.plugins maven-dependency-plugin - 3.8.0 + 3.8.1 org.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 128/255] 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 129/255] 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.plugins maven-javadoc-plugin - 3.10.1 + 3.11.1 true false 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 130/255] 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 131/255] 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}/apidocs true *.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 132/255] 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 133/255] 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 134/255] 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 135/255] 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 136/255] 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 137/255] 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 138/255] 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 139/255] 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 140/255] 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 + junit junit 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 141/255] 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 142/255] 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 143/255] 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 144/255] 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 145/255] 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 146/255] 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 147/255] 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 148/255] 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 149/255] 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 150/255] 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 151/255] 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 152/255] 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 + 23 16 @@ -533,8 +532,8 @@ - - 22 + + 23 16 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 153/255] 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 @@ install it/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 @@

      New Features

      (GitHub #1700).
    • Experimental support for Java 24 class files (GitHub #1631).
    • +
    • Experimental support for Java 25 class files + (GitHub #1807).
    • Part of bytecode generated by the Kotlin Compose compiler plugin is filtered out during generation of report (GitHub #1616).
    • diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html index 8dabc61b4b..27c5cae347 100644 --- a/org.jacoco.doc/docroot/doc/faq.html +++ b/org.jacoco.doc/docroot/doc/faq.html @@ -45,10 +45,11 @@

      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 159/255] 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 160/255] 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 161/255] 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 162/255] 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.plugins maven-javadoc-plugin - 3.11.1 + 3.11.2 true false 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 163/255] 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 164/255] 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.maven sonar-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 165/255] 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); + } + } + } + + /** + *
      +	 * DUP
      +	 * IFNULL label
      +	 * ... // call 0
      +	 *
      +	 * ...
      +	 *
      +	 * DUP
      +	 * IFNULL label
      +	 * ... // call N
      +	 *
      +	 * label:
      +	 * POP
      +	 * 
      + */ + private static Collection> findChains( + final MethodNode methodNode) { + final HashMap> chains = new HashMap>(); + for (final AbstractInsnNode i : methodNode.instructions) { + if (i.getOpcode() == Opcodes.IFNULL + && i.getPrevious().getOpcode() == Opcodes.DUP) { + final JumpInsnNode jump = (JumpInsnNode) i; + final LabelNode label = jump.label; + if (AbstractMatcher.skipNonOpcodes(label.getNext()) + .getOpcode() != Opcodes.POP) { + continue; + } + ArrayList chain = chains.get(label); + if (chain == null) { + chain = new ArrayList(); + chains.put(label, chain); + } + chain.add(jump); + } + } + return chains.values(); + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index c4ce95b553..e098ee6d0d 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -49,6 +49,9 @@

      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 chains of safe call + operators is filtered out during generation of report + (GitHub #1810).
    • Method getEntries generated by the Kotlin compiler for enum classes is filtered out during generation of report (GitHub #1625).
    • From 1b2ebc3cd415c272b92c60d708b6d3b459a52d8b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 16 Dec 2024 18:52:45 +0100 Subject: [PATCH 166/255] Extract `KotlinSyntheticAccessorsFilter` from `SyntheticFilter` (#1811) --- .../filter/KotlinSyntheticFilterTest.java | 167 ++++++++++++++++++ .../analysis/filter/SyntheticFilterTest.java | 140 --------------- .../internal/analysis/filter/Filters.java | 1 + .../KotlinSyntheticAccessorsFilter.java | 38 ++++ .../analysis/filter/SyntheticFilter.java | 12 +- 5 files changed, 211 insertions(+), 147 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java new file mode 100644 index 0000000000..b1cdd75351 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * 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 org.jacoco.core.internal.instr.InstrSupport; +import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link KotlinSyntheticAccessorsFilter}. + */ +public class KotlinSyntheticFilterTest extends FilterTestBase { + + private final IFilter filter = new KotlinSyntheticAccessorsFilter(); + + /** + *
      +	 * @JvmSynthetic
      +	 * fun example() {
      +	 * }
      +	 * 
      + * + * @see #should_filter_synthetic_accessor_methods_in_Kotlin_classes() + */ + @Test + public void should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "example", "()V", null, null); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + + /** + *
      +	 * class Outer {
      +	 *   private var x = 42
      +	 *
      +	 *   inner class Inner {
      +	 *     fun example() {
      +	 *       x += 1
      +	 *     }
      +	 *   }
      +	 * }
      +	 * 
      + * + * @see #should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() + */ + @Test + public void should_filter_synthetic_accessor_methods_in_Kotlin_classes() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "access$getX$p", "(Outer;)I", null, + null); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "Outer", "x", "I"); + m.visitInsn(Opcodes.IRETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + @Test + public void should_not_filter_method_with_suffix_default_in_kotlin_classes() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE, "example$default", + "(LTarget;Ljava/lang/String;Ijava/lang/Object;)V", null, null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + + @Test + public void should_not_filter_synthetic_constructor_containing_default_arguments_in_kotlin_classes() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC, "", + "(IILkotlin/jvm/internal/DefaultConstructorMarker;)V", null, + null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + + /** + * For private suspending function Kotlin compiler versions prior to 1.5 + * produce package-local synthetic method that should not be filtered + * + *
      +	 * private suspend fun example() {
      +	 * }
      +	 * 
      + * + * @see #should_filter_synthetic_methods_whose_name_starts_with_access_dollar_even_if_last_argument_is_kotlin_coroutine_continuation() + */ + @Test + public void should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_coroutine_continuation() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "example", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, + null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertIgnored(); + } + + /** + * For private suspending function Kotlin compiler versions starting from + * 1.5 produce additional public synthetic method with name starting with + * "access$" that should be filtered + * + *
      +	 * private suspend fun example() {
      +	 * }
      +	 * 
      + * + * @see #should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_coroutine_continuation() + */ + @Test + public void should_filter_synthetic_methods_whose_name_starts_with_access_dollar_even_if_last_argument_is_kotlin_coroutine_continuation() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL + | Opcodes.ACC_SYNTHETIC, + "access$example", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, + null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "example", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java index d0cd63f417..bdc502b35b 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java @@ -57,59 +57,6 @@ public void testLambda() { assertIgnored(); } - /** - *
      -	 * @JvmSynthetic
      -	 * fun example() {
      -	 * }
      -	 * 
      - * - * @see #should_filter_synthetic_accessor_methods_in_Kotlin_classes() - */ - @Test - public void should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() { - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_SYNTHETIC, "example", "()V", null, null); - m.visitInsn(Opcodes.RETURN); - - filter.filter(m, context, output); - - assertIgnored(); - } - - /** - *
      -	 * class Outer {
      -	 *   private var x = 42
      -	 *
      -	 *   inner class Inner {
      -	 *     fun example() {
      -	 *       x += 1
      -	 *     }
      -	 *   }
      -	 * }
      -	 * 
      - * - * @see #should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() - */ - @Test - public void should_filter_synthetic_accessor_methods_in_Kotlin_classes() { - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_SYNTHETIC, "access$getX$p", "(Outer;)I", null, - null); - m.visitVarInsn(Opcodes.ALOAD, 0); - m.visitFieldInsn(Opcodes.GETFIELD, "Outer", "x", "I"); - m.visitInsn(Opcodes.IRETURN); - - filter.filter(m, context, output); - - assertMethodIgnored(m); - } - @Test public void should_filter_synthetic_method_with_prefix_anonfun_in_non_Scala_classes() { final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, @@ -142,20 +89,6 @@ public void should_not_filter_synthetic_method_with_prefix_anonfun_in_Scala_inne assertIgnored(); } - @Test - public void should_not_filter_method_with_suffix_default_in_kotlin_classes() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE, "example$default", - "(LTarget;Ljava/lang/String;Ijava/lang/Object;)V", null, null); - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - m.visitInsn(Opcodes.NOP); - - filter.filter(m, context, output); - - assertIgnored(); - } - @Test public void should_filter_synthetic_method_with_suffix_default_in_non_kotlin_classes() { final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, @@ -168,77 +101,4 @@ public void should_filter_synthetic_method_with_suffix_default_in_non_kotlin_cla assertMethodIgnored(m); } - @Test - public void should_not_filter_synthetic_constructor_containing_default_arguments_in_kotlin_classes() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_SYNTHETIC, "", - "(IILkotlin/jvm/internal/DefaultConstructorMarker;)V", null, - null); - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - m.visitInsn(Opcodes.NOP); - - filter.filter(m, context, output); - - assertIgnored(); - } - - /** - * For private suspending function Kotlin compiler versions prior to 1.5 - * produce package-local synthetic method that should not be filtered - * - *
      -	 * private suspend fun example() {
      -	 * }
      -	 * 
      - * - * @see #should_filter_synthetic_methods_whose_name_starts_with_access_dollar_even_if_last_argument_is_kotlin_coroutine_continuation() - */ - @Test - public void should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_coroutine_continuation() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "example", - "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, - null); - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - m.visitInsn(Opcodes.NOP); - - filter.filter(m, context, output); - - assertIgnored(); - } - - /** - * For private suspending function Kotlin compiler versions starting from - * 1.5 produce additional public synthetic method with name starting with - * "access$" that should be filtered - * - *
      -	 * private suspend fun example() {
      -	 * }
      -	 * 
      - * - * @see #should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_coroutine_continuation() - */ - @Test - public void should_filter_synthetic_methods_whose_name_starts_with_access_dollar_even_if_last_argument_is_kotlin_coroutine_continuation() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, - Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL - | Opcodes.ACC_SYNTHETIC, - "access$example", - "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, - null); - context.classAnnotations - .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); - m.visitVarInsn(Opcodes.ALOAD, 0); - m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "example", - "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false); - m.visitInsn(Opcodes.RETURN); - - filter.filter(m, context, output); - - assertMethodIgnored(m); - } - } 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 1f7e600edd..34754d3cb5 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 @@ -43,6 +43,7 @@ public static IFilter all() { new ExhaustiveSwitchFilter(), // new RecordPatternFilter(), // new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(), + new KotlinSyntheticAccessorsFilter(), // new KotlinEnumFilter(), // new KotlinSafeCallOperatorFilter(), // new KotlinLateinitFilter(), new KotlinWhenFilter(), diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java new file mode 100644 index 0000000000..c580f83d5c --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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 org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters synthetic accessors generated by the Kotlin compiler. + */ +final class KotlinSyntheticAccessorsFilter implements IFilter { + + public void filter(MethodNode methodNode, IFilterContext context, + IFilterOutput output) { + if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { + return; + } + if (!Filters.isKotlinClass(context)) { + return; + } + if (!methodNode.name.startsWith("access$")) { + return; + } + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + +} 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 f260d01cf2..fde5d3a744 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 @@ -16,7 +16,8 @@ import org.objectweb.asm.tree.MethodNode; /** - * Filters synthetic methods unless they represent bodies of lambda expressions. + * Filters synthetic methods in non-Kotlin classes unless they represent bodies + * of lambda expressions. */ final class SyntheticFilter implements IFilter { @@ -30,6 +31,9 @@ public void filter(final MethodNode methodNode, if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { return; } + if (Filters.isKotlinClass(context)) { + return; + } if (methodNode.name.startsWith("lambda$")) { return; @@ -41,12 +45,6 @@ public void filter(final MethodNode methodNode, } } - if (Filters.isKotlinClass(context)) { - if (!methodNode.name.startsWith("access$")) { - return; - } - } - output.ignore(methodNode.instructions.getFirst(), methodNode.instructions.getLast()); } From 451e6b6b64161c1e18730160c6248ca8aa176874 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:49:08 +0100 Subject: [PATCH 167/255] Upgrade maven-invoker-plugin to 3.9.0 (#1817) Bump org.apache.maven.plugins:maven-invoker-plugin in /org.jacoco.build Bumps [org.apache.maven.plugins:maven-invoker-plugin](https://github.com/apache/maven-invoker-plugin) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/apache/maven-invoker-plugin/releases) - [Commits](https://github.com/apache/maven-invoker-plugin/compare/maven-invoker-plugin-3.8.1...maven-invoker-plugin-3.9.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-invoker-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 4fa5493de5..2de8f12a45 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -338,7 +338,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.8.1 + 3.9.0 org.apache.maven.plugins From b1ad67d3009c29a6725a2548721041140a577a54 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:54:00 +0100 Subject: [PATCH 168/255] IntelliJ IDEA should not suggest import of `jdk.internal.*` classes (#1820) Without this change IntelliJ shows me first `jdk.internal.org.objectweb.asm.Opcodes` in the list of suggestions and only then `org.objectweb.asm.Opcodes`. --- .idea/codeInsightSettings.xml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .idea/codeInsightSettings.xml diff --git a/.idea/codeInsightSettings.xml b/.idea/codeInsightSettings.xml new file mode 100644 index 0000000000..62ce4d17bd --- /dev/null +++ b/.idea/codeInsightSettings.xml @@ -0,0 +1,8 @@ + + + + + jdk.internal.* + + + \ No newline at end of file From 1e37ea8645e4702bcc6a817adf08864a987fd19b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 17 Dec 2024 23:43:31 +0100 Subject: [PATCH 169/255] Add validation test for `Serializable` lambda in Java (#1698) --- .../java8/LambdaSerializableTest.java | 51 +++++++++++++++++++ .../targets/LambdaSerializableTarget.java | 33 ++++++++++++ .../core/test/validation/targets/Stubs.java | 14 +++++ 3 files changed, 98 insertions(+) create mode 100644 org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaSerializableTest.java create mode 100644 org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaSerializableTarget.java diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaSerializableTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaSerializableTest.java new file mode 100644 index 0000000000..399383e39b --- /dev/null +++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaSerializableTest.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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.java8; + +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; +import java.util.HashSet; + +import org.jacoco.core.test.validation.ValidationTestBase; +import org.jacoco.core.test.validation.java8.targets.LambdaSerializableTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link LambdaSerializableTarget}. + */ +public class LambdaSerializableTest extends ValidationTestBase { + + public LambdaSerializableTest() { + super(LambdaSerializableTarget.class); + } + + @Test + public void compiler_should_generate_synthetic_deserializeLambda() { + final HashSet names = new HashSet<>(); + for (final Method method : LambdaSerializableTarget.class + .getDeclaredMethods()) { + if (method.isSynthetic()) { + names.add(method.getName()); + } + } + + assertTrue(names.contains("$deserializeLambda$")); + } + + @Test + public void test_method_count() { + assertMethodCount(/* constructor + main + lambda */ 3); + } + +} diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaSerializableTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaSerializableTarget.java new file mode 100644 index 0000000000..78b7216d0d --- /dev/null +++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaSerializableTarget.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.java8.targets; + +import static org.jacoco.core.test.validation.targets.Stubs.execSerializable; +import static org.jacoco.core.test.validation.targets.Stubs.nop; + +import java.io.Serializable; + +/** + * Test target with {@link Serializable} lambda. + */ +public class LambdaSerializableTarget { + + public static void main(String[] args) { + + execSerializable(() -> { + nop(); // assertFullyCovered() + }); + + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java index 9e0a723b66..8c5b2d8dad 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java +++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.jacoco.core.test.validation.targets; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,12 @@ public SuperClass(boolean arg) { } + /** + * Serializable functional interface stub. + */ + public interface SerializableRunnable extends Serializable, Runnable { + } + /** * Enum stub. */ @@ -144,6 +151,13 @@ public static void exec(Runnable task) { public static void noexec(Runnable task) { } + /** + * Directly executes the given {@link SerializableRunnable}. + */ + public static void execSerializable(SerializableRunnable task) { + task.run(); + } + /** * List of logged events. Using a static member here works as this class is * loaded in a new class loader for every test case. From 22ead5e845a3db08b0f3051eb9f2fe8e6edcf827 Mon Sep 17 00:00:00 2001 From: "Marc R. Hoffmann" Date: Wed, 18 Dec 2024 00:50:16 +0100 Subject: [PATCH 170/255] Get rid of repetitive execution of `isKotlinClass` in Kotlin filters (#1809) Co-authored-by: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> --- .../KotlinDefaultArgumentsFilterTest.java | 11 --- .../KotlinDefaultMethodsFilterTest.java | 14 --- .../analysis/filter/KotlinEnumFilterTest.java | 15 ---- .../filter/KotlinGeneratedFilterTest.java | 12 --- .../filter/KotlinInlineClassFilterTest.java | 12 --- .../filter/KotlinInlineFilterTest.java | 12 --- .../KotlinUnsafeCastOperatorFilterTest.java | 19 ---- .../internal/analysis/filter/FilterSet.java | 35 ++++++++ .../internal/analysis/filter/Filters.java | 90 +++++++++++-------- .../analysis/filter/KotlinComposeFilter.java | 3 - .../filter/KotlinCoroutineFilter.java | 5 -- .../filter/KotlinDefaultArgumentsFilter.java | 6 +- .../filter/KotlinDefaultMethodsFilter.java | 3 - .../analysis/filter/KotlinEnumFilter.java | 3 - .../filter/KotlinGeneratedFilter.java | 5 -- .../filter/KotlinInlineClassFilter.java | 3 - .../analysis/filter/KotlinInlineFilter.java | 8 +- .../filter/KotlinSafeCallOperatorFilter.java | 5 +- .../KotlinUnsafeCastOperatorFilter.java | 3 - 19 files changed, 94 insertions(+), 170 deletions(-) create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java index 6b66fabc18..bb4f3d2a35 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java @@ -63,17 +63,6 @@ public void should_filter() { assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); } - @Test - public void should_not_filter_when_not_kotlin() { - final MethodNode m = createMethod(Opcodes.ACC_SYNTHETIC, - "not_kotlin_synthetic$default", - "(LTarget;IILjava/lang/Object;)V"); - - filter.filter(m, context, output); - - assertIgnored(); - } - @Test public void should_not_filter_when_suffix_absent() { final MethodNode m = createMethod(Opcodes.ACC_SYNTHETIC, diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java index efa37ff891..58d6330379 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java @@ -69,18 +69,4 @@ public void should_not_filter_when_instructions_do_not_match() { assertIgnored(); } - @Test - public void should_not_filter_when_not_kotlin() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, - "m", "()V", null, null); - m.visitVarInsn(Opcodes.ALOAD, 0); - m.visitMethodInsn(Opcodes.INVOKESTATIC, "Target$DefaultImpls", "m", - "(LTarget;)V", false); - m.visitInsn(Opcodes.RETURN); - - filter.filter(m, context, output); - - assertIgnored(); - } - } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java index 2c3a885132..1fcfeae54e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java @@ -61,21 +61,6 @@ public void should_not_filter_when_not_Enum() { assertIgnored(); } - @Test - public void should_not_filter_when_not_Kotlin() { - context.superClassName = "java/lang/Enum"; - final MethodNode m = new MethodNode( - Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getEntries", - "()Lkotlin/enums/EnumEntries;", null, null); - m.visitFieldInsn(Opcodes.GETSTATIC, "Example", "$ENTRIES", - "Lkotlin/enums/EnumEntries;"); - m.visitInsn(Opcodes.ARETURN); - - filter.filter(m, context, output); - - assertIgnored(); - } - @Test public void should_not_filter_when_not_getEntries_name() { context.superClassName = "java/lang/Enum"; diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java index f0b01765de..a00c609cde 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java @@ -55,18 +55,6 @@ public void testWithLinesForKotlinWithDebug() { assertIgnored(); } - @Test - public void testNoLinesNonKotlinWithDebug() { - final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, - "hashCode", "()I", null, null); - m.visitInsn(Opcodes.ICONST_0); - m.visitInsn(Opcodes.IRETURN); - - filter.filter(m, context, output); - - assertIgnored(); - } - @Test public void testNoLinesForKotlinNoDebug() { final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java index 8fd77a0a4e..99a4a86902 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java @@ -83,16 +83,4 @@ public void should_not_filter_when_no_JvmInline_annotation() { assertIgnored(); } - @Test - public void should_not_filter_when_not_kotlin() { - context.classAnnotations.add("Lkotlin/jvm/JvmInline;"); - final MethodNode m = new MethodNode(0, "getValue", - "()Ljava/lang/String;", null, null); - m.visitInsn(Opcodes.NOP); - - filter.filter(m, context, output); - - assertIgnored(); - } - } 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 161faea31f..f54bd641e3 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 @@ -284,18 +284,6 @@ public void should_filter_all_lines() { assertIgnored(expectedRanges.toArray(new Range[0])); } - @Test - public void should_not_parse_SourceDebugExtension_attribute_when_no_kotlin_metadata_annotation() { - context.sourceDebugExtension = "SMAP"; - - m.visitLineNumber(1, new Label()); - m.visitInsn(Opcodes.RETURN); - - filter.filter(m, context, output); - - assertIgnored(); - } - @Test public void should_not_filter_when_no_SourceDebugExtension_attribute() { context.classAnnotations diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index 2abd150952..5d4584424c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -146,23 +146,4 @@ public void should_filter_Kotlin_1_6() { assertIgnored(new Range(expectedFrom, expectedTo)); } - @Test - public void should_not_filter_when_not_kotlin() { - m.visitInsn(Opcodes.DUP); - final Label label = new Label(); - m.visitJumpInsn(Opcodes.IFNONNULL, label); - m.visitTypeInsn(Opcodes.NEW, "java/lang/NullPointerException"); - m.visitInsn(Opcodes.DUP); - m.visitLdcInsn("null cannot be cast to non-null type kotlin.String"); - m.visitMethodInsn(Opcodes.INVOKESPECIAL, - "java/lang/NullPointerException", "", - "(Ljava/lang/String;)V", false); - m.visitInsn(Opcodes.ATHROW); - m.visitLabel(label); - - filter.filter(m, context, output); - - assertIgnored(); - } - } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java new file mode 100644 index 0000000000..f998ede6f2 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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 org.objectweb.asm.tree.MethodNode; + +/** + * Filter that combines other filters. + */ +class FilterSet implements IFilter { + + private final IFilter[] filters; + + FilterSet(final IFilter... filters) { + this.filters = filters; + } + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + for (final IFilter filter : filters) { + filter.filter(methodNode, context, 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 34754d3cb5..79ab5b1bc8 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 @@ -15,56 +15,76 @@ import org.objectweb.asm.tree.MethodNode; /** - * Filter that combines other filters. + * Factory for all JaCoCo filters. */ -public final class Filters implements IFilter { +public final class Filters { + + private Filters() { + // no instances + } /** * Filter that does nothing. */ - public static final IFilter NONE = new Filters(); - - private final IFilter[] filters; + public static final IFilter NONE = new FilterSet(); /** - * Creates filter that combines all other filters. + * Creates a filter that combines all filters. * - * @return filter that combines all other filters + * @return filter that combines all filters */ public static IFilter all() { - return new Filters(new EnumFilter(), new SyntheticFilter(), - new BridgeFilter(), new SynchronizedFilter(), - new TryWithResourcesJavac11Filter(), - new TryWithResourcesJavacFilter(), - new TryWithResourcesEcjFilter(), new FinallyFilter(), - new PrivateEmptyNoArgConstructorFilter(), new AssertFilter(), - new StringSwitchJavacFilter(), new StringSwitchFilter(), - new EnumEmptyConstructorFilter(), new RecordsFilter(), + return new FilterSet( // + allCommonFilters(), // + allKotlinFilters()); + } + + private static IFilter allCommonFilters() { + return new FilterSet( // + new EnumFilter(), // + new SyntheticFilter(), // + new BridgeFilter(), // + new SynchronizedFilter(), // + new TryWithResourcesJavac11Filter(), // + new TryWithResourcesJavacFilter(), // + new TryWithResourcesEcjFilter(), // + new FinallyFilter(), // + new PrivateEmptyNoArgConstructorFilter(), // + new AssertFilter(), // + new StringSwitchJavacFilter(), // + new StringSwitchFilter(), // + new EnumEmptyConstructorFilter(), // + new RecordsFilter(), // new ExhaustiveSwitchFilter(), // new RecordPatternFilter(), // - new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(), + new AnnotationGeneratedFilter()); + } + + private static IFilter allKotlinFilters() { + return new FilterSet( // + new KotlinGeneratedFilter(), // new KotlinSyntheticAccessorsFilter(), // new KotlinEnumFilter(), // new KotlinSafeCallOperatorFilter(), // - new KotlinLateinitFilter(), new KotlinWhenFilter(), - new KotlinWhenStringFilter(), - new KotlinUnsafeCastOperatorFilter(), - new KotlinNotNullOperatorFilter(), - new KotlinInlineClassFilter(), - new KotlinDefaultArgumentsFilter(), new KotlinInlineFilter(), - new KotlinCoroutineFilter(), new KotlinDefaultMethodsFilter(), - new KotlinComposeFilter()); - } - - private Filters(final IFilter... filters) { - this.filters = filters; - } - - public void filter(final MethodNode methodNode, - final IFilterContext context, final IFilterOutput output) { - for (final IFilter filter : filters) { - filter.filter(methodNode, context, output); - } + new KotlinLateinitFilter(), // + new KotlinWhenFilter(), // + new KotlinWhenStringFilter(), // + new KotlinUnsafeCastOperatorFilter(), // + new KotlinNotNullOperatorFilter(), // + new KotlinInlineClassFilter(), // + new KotlinDefaultArgumentsFilter(), // + new KotlinInlineFilter(), // + new KotlinCoroutineFilter(), // + new KotlinDefaultMethodsFilter(), // + new KotlinComposeFilter()) { + @Override + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + if (isKotlinClass(context)) { + super.filter(methodNode, context, 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 62a53d9235..6c57d4e626 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,9 +26,6 @@ final class KotlinComposeFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - if (!Filters.isKotlinClass(context)) { - return; - } if (!isComposable(methodNode)) { return; } 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 c83c28b8cc..8107845038 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 @@ -30,11 +30,6 @@ final class KotlinCoroutineFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - - if (!Filters.isKotlinClass(context)) { - return; - } - new Matcher().match(methodNode, output); new Matcher().matchOptimizedTailCall(methodNode, output); } 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 61643f138d..f5d5de2824 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 @@ -76,10 +76,6 @@ public void filter(final MethodNode methodNode, if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { return; } - if (!Filters.isKotlinClass(context)) { - return; - } - if (isDefaultArgumentsMethod(methodNode)) { new Matcher().match(methodNode, output, false); } else if (isDefaultArgumentsConstructor(methodNode)) { @@ -133,7 +129,7 @@ public void match(final MethodNode methodNode, skipNonOpcodes(); } - for (AbstractInsnNode i : ignore) { + for (final AbstractInsnNode i : ignore) { output.ignore(i, i); } } 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 d79952216b..3ee8d06dfd 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,9 +24,6 @@ final class KotlinDefaultMethodsFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - 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 43737cd6f0..ea91cdd61e 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,9 +25,6 @@ public void filter(final MethodNode methodNode, if (!"java/lang/Enum".equals(context.getSuperClassName())) { return; } - if (!Filters.isKotlinClass(context)) { - return; - } if (!"getEntries".equals(methodNode.name)) { return; } 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 7e7b67e0b6..7d4a2cef2a 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 @@ -32,11 +32,6 @@ public void filter(final MethodNode methodNode, // disabled filtering as all methods might be erroneously skipped return; } - - if (!Filters.isKotlinClass(context)) { - return; - } - if (hasLineNumber(methodNode)) { for (final AbstractInsnNode i : methodNode.instructions) { if (AbstractInsnNode.LINE == i.getType()) { 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 41ad6d4e19..bf46771cf5 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,9 +73,6 @@ final class KotlinInlineClassFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - if (!Filters.isKotlinClass(context)) { - return; - } if (!context.getClassAnnotations().contains("Lkotlin/jvm/JvmInline;")) { return; } 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 1a3bbe9e7c..f323de3212 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 @@ -29,10 +29,6 @@ public void filter(final MethodNode methodNode, return; } - if (!Filters.isKotlinClass(context)) { - return; - } - if (firstGeneratedLineNumber == -1) { firstGeneratedLineNumber = getFirstGeneratedLineNumber( context.getClassName(), context.getSourceFileName(), @@ -53,8 +49,8 @@ public void filter(final MethodNode methodNode, 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()) { + for (final KotlinSMAP.Mapping mapping : new KotlinSMAP(sourceFileName, + smap).mappings()) { if (className.equals(mapping.inputClassName()) && mapping.inputStartLine() == mapping.outputStartLine()) { continue; 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 index 887ff7ad87..c3fdec96eb 100644 --- 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 @@ -31,14 +31,11 @@ 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 JumpInsnNode lastJump = chain.get(chain.size() - 1); final HashSet newTargets = new HashSet(); newTargets.add(AbstractMatcher.skipNonOpcodes(lastJump.getNext())); newTargets.add(AbstractMatcher.skipNonOpcodes(lastJump.label)); 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 559bda4b21..35af5efdb7 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 @@ -26,9 +26,6 @@ final class KotlinUnsafeCastOperatorFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - if (!Filters.isKotlinClass(context)) { - return; - } final Matcher matcher = new Matcher(); for (final AbstractInsnNode i : methodNode.instructions) { matcher.match("kotlin/TypeCastException", i, output); From 70a82d91eac20b0b9286ac728ca63a27157fbc3a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:48:35 +0100 Subject: [PATCH 171/255] Add validation test for `Serializable` lambda in Kotlin (#1699) --- .../kotlin/KotlinLambdaSerializableTest.java | 52 +++++++++++++++++++ .../targets/KotlinLambdaSerializableTarget.kt | 32 ++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLambdaSerializableTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLambdaSerializableTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLambdaSerializableTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLambdaSerializableTest.java new file mode 100644 index 0000000000..bd6a7ef0ca --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLambdaSerializableTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; + +import org.jacoco.core.test.validation.ValidationTestBase; +import org.jacoco.core.test.validation.kotlin.targets.KotlinLambdaSerializableTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinLambdaSerializableTarget}. + */ +public class KotlinLambdaSerializableTest extends ValidationTestBase { + + public KotlinLambdaSerializableTest() { + super(KotlinLambdaSerializableTarget.class); + } + + @Test + public void compiler_should_generate_synthetic_deserializeLambda() { + final HashSet names = new HashSet(); + for (final Method method : KotlinLambdaSerializableTarget.class + .getDeclaredMethods()) { + if (method.isSynthetic()) { + names.add(method.getName()); + } + } + + assertEquals(Collections.singleton("$deserializeLambda$"), names); + } + + @Test + public void test_method_count() { + assertMethodCount(/* main + lambda */ 2); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLambdaSerializableTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLambdaSerializableTarget.kt new file mode 100644 index 0000000000..8d35464b81 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLambdaSerializableTarget.kt @@ -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.targets + +import org.jacoco.core.test.validation.targets.Stubs.execSerializable +import org.jacoco.core.test.validation.targets.Stubs.nop + +/** + * Test target with [java.io.Serializable] lambda. + */ +object KotlinLambdaSerializableTarget { + + @JvmStatic + fun main(args: Array) { + + execSerializable { + nop() // assertFullyCovered() + } + + } + +} From f59a132c87ca4bd7e975a6790191c3b7984a5276 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:28:26 +0100 Subject: [PATCH 172/255] =?UTF-8?q?Get=20rid=20of=20cycle=20Filters.allKot?= =?UTF-8?q?linFilters=20=E2=86=92=20SyntheticFilter=20=E2=86=92=20Filters.?= =?UTF-8?q?isKotlinClass=20(#1822)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/analysis/filter/FilterSet.java | 2 +- .../internal/analysis/filter/Filters.java | 33 +++++++++++-------- .../KotlinSyntheticAccessorsFilter.java | 3 -- .../analysis/filter/SyntheticFilter.java | 3 -- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java index f998ede6f2..33cc26f9b6 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FilterSet.java @@ -17,7 +17,7 @@ /** * Filter that combines other filters. */ -class FilterSet implements IFilter { +final class FilterSet implements IFilter { private final IFilter[] filters; 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 79ab5b1bc8..172c96bbfb 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 @@ -34,15 +34,25 @@ private Filters() { * @return filter that combines all filters */ public static IFilter all() { - return new FilterSet( // - allCommonFilters(), // - allKotlinFilters()); + final IFilter allCommonFilters = allCommonFilters(); + final IFilter allKotlinFilters = allKotlinFilters(); + final IFilter allNonKotlinFilters = allNonKotlinFilters(); + return new IFilter() { + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + allCommonFilters.filter(methodNode, context, output); + if (isKotlinClass(context)) { + allKotlinFilters.filter(methodNode, context, output); + } else { + allNonKotlinFilters.filter(methodNode, context, output); + } + } + }; } private static IFilter allCommonFilters() { return new FilterSet( // new EnumFilter(), // - new SyntheticFilter(), // new BridgeFilter(), // new SynchronizedFilter(), // new TryWithResourcesJavac11Filter(), // @@ -60,6 +70,11 @@ private static IFilter allCommonFilters() { new AnnotationGeneratedFilter()); } + private static IFilter allNonKotlinFilters() { + return new FilterSet( // + new SyntheticFilter()); + } + private static IFilter allKotlinFilters() { return new FilterSet( // new KotlinGeneratedFilter(), // @@ -76,15 +91,7 @@ private static IFilter allKotlinFilters() { new KotlinInlineFilter(), // new KotlinCoroutineFilter(), // new KotlinDefaultMethodsFilter(), // - new KotlinComposeFilter()) { - @Override - public void filter(final MethodNode methodNode, - final IFilterContext context, final IFilterOutput output) { - if (isKotlinClass(context)) { - super.filter(methodNode, context, output); - } - } - }; + new KotlinComposeFilter()); } /** diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java index c580f83d5c..e92f0756e5 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticAccessorsFilter.java @@ -25,9 +25,6 @@ public void filter(MethodNode methodNode, IFilterContext context, if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { return; } - if (!Filters.isKotlinClass(context)) { - return; - } if (!methodNode.name.startsWith("access$")) { return; } 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 fde5d3a744..dea5ed0261 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 @@ -31,9 +31,6 @@ public void filter(final MethodNode methodNode, if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { return; } - if (Filters.isKotlinClass(context)) { - return; - } if (methodNode.name.startsWith("lambda$")) { return; From e21a0b13a9da4aecb4b3c60faeacf45a5b11b9db Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 21 Dec 2024 02:32:43 +0100 Subject: [PATCH 173/255] StringSwitchFilter should handle Kotlin nullable String (#1769) --- .../kotlin/targets/KotlinWhenStringTarget.kt | 28 +++ .../filter/StringSwitchFilterTest.java | 224 ++++++++++++++++-- .../analysis/filter/StringSwitchFilter.java | 32 ++- org.jacoco.doc/docroot/doc/changes.html | 4 + 4 files changed, 268 insertions(+), 20 deletions(-) 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 index 234c141221..57415b6b64 100644 --- 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 @@ -27,6 +27,23 @@ object KotlinWhenStringTarget { else -> 7 // assertFullyCovered() } // assertFullyCovered() + private fun whenStringNullableDefault(p: String?): String = + when (p) { // assertFullyCovered(0, 4) + "a" -> "case a" // assertFullyCovered() + "b" -> "case b" // assertFullyCovered() + "c" -> "case c" // assertFullyCovered() + else -> "else" // assertFullyCovered() + } // assertFullyCovered() + + private fun whenStringNullableCase(p: String?): String = + when (p) { // assertFullyCovered(0, 5) + "a" -> "case a" // assertFullyCovered() + "b" -> "case b" // assertFullyCovered() + "c" -> "case c" // assertFullyCovered() + null -> "null" // assertFullyCovered() + else -> "else" // assertFullyCovered() + } // assertFullyCovered() + /** * Unlike [whenString] * in this example first case is the only case with biggest hashCode value. @@ -51,6 +68,17 @@ object KotlinWhenStringTarget { whenString("\u0000b") whenString("\u0000c") + whenStringNullableDefault("a") + whenStringNullableDefault("b") + whenStringNullableDefault("c") + whenStringNullableDefault("") + + whenStringNullableCase("a") + whenStringNullableCase("b") + whenStringNullableCase("c") + whenStringNullableCase(null) + whenStringNullableCase("") + whenStringBiggestHashCodeFirst("") whenStringBiggestHashCodeFirst("a") whenStringBiggestHashCodeFirst("b") diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java index 8a8be810e0..68d6b4d3fd 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java @@ -31,6 +31,7 @@ public class StringSwitchFilterTest extends FilterTestBase { @Test public void should_filter() { + final Range range = new Range(); final Set expectedNewTargets = new HashSet(); final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, @@ -53,8 +54,8 @@ public void should_filter() { m.visitVarInsn(Opcodes.ASTORE, 2); m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false); + range.fromInclusive = m.instructions.getLast(); m.visitTableSwitchInsn(97, 98, caseDefault, h1, h2); - final AbstractInsnNode switchNode = m.instructions.getLast(); m.visitLabel(h1); @@ -86,7 +87,7 @@ public void should_filter() { // goto default case m.visitJumpInsn(Opcodes.GOTO, caseDefault); - final AbstractInsnNode expectedToInclusive = m.instructions.getLast(); + range.toInclusive = m.instructions.getLast(); m.visitLabel(case1); m.visitInsn(Opcodes.RETURN); @@ -103,12 +104,14 @@ public void should_filter() { filter.filter(m, context, output); - assertReplacedBranches(switchNode, expectedNewTargets); - assertIgnored(new Range(switchNode.getNext(), expectedToInclusive)); + assertIgnored(range); + assertReplacedBranches(range.fromInclusive.getPrevious(), + expectedNewTargets); } @Test public void should_filter_when_default_is_first() { + final Range range = new Range(); final Set expectedNewTargets = new HashSet(); final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, @@ -128,20 +131,18 @@ public void should_filter_when_default_is_first() { m.visitVarInsn(Opcodes.ASTORE, 2); m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false); + range.fromInclusive = m.instructions.getLast(); m.visitLookupSwitchInsn(caseDefault, new int[] { 97 }, new Label[] { h1 }); - final AbstractInsnNode switchNode = m.instructions.getLast(); m.visitLabel(h1); - m.visitVarInsn(Opcodes.ALOAD, 2); m.visitLdcInsn("a"); m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); // if equal "a", then goto its case m.visitJumpInsn(Opcodes.IFNE, case1); - - final AbstractInsnNode expectedToInclusive = m.instructions.getLast(); + range.toInclusive = m.instructions.getLast(); m.visitLabel(caseDefault); m.visitInsn(Opcodes.RETURN); @@ -152,8 +153,9 @@ public void should_filter_when_default_is_first() { filter.filter(m, context, output); - assertReplacedBranches(switchNode, expectedNewTargets); - assertIgnored(new Range(switchNode.getNext(), expectedToInclusive)); + assertIgnored(range); + assertReplacedBranches(range.fromInclusive.getPrevious(), + expectedNewTargets); } /** @@ -172,6 +174,7 @@ public void should_filter_when_default_is_first() { */ @Test public void should_filter_Kotlin_1_5() { + final Range range = new Range(); final Set expectedNewTargets = new HashSet(); final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, @@ -188,13 +191,14 @@ public void should_filter_Kotlin_1_5() { final Label case5 = new Label(); final Label case6 = new Label(); + m.visitVarInsn(Opcodes.ASTORE, 1); m.visitVarInsn(Opcodes.ALOAD, 1); + range.fromInclusive = m.instructions.getLast(); m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false); m.visitTableSwitchInsn(97, 99, defaultCase, h1, h2, h3); m.visitLabel(h1); - final AbstractInsnNode expectedFromInclusive = m.instructions.getLast(); m.visitVarInsn(Opcodes.ALOAD, 1); m.visitLdcInsn("a"); m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", @@ -238,7 +242,7 @@ public void should_filter_Kotlin_1_5() { m.visitJumpInsn(Opcodes.IFNE, case6); m.visitJumpInsn(Opcodes.GOTO, defaultCase); - final AbstractInsnNode expectedToInclusive = m.instructions.getLast(); + range.toInclusive = m.instructions.getLast(); m.visitLabel(case1); m.visitInsn(Opcodes.RETURN); @@ -264,8 +268,200 @@ public void should_filter_Kotlin_1_5() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFromInclusive, expectedToInclusive)); - assertReplacedBranches(expectedFromInclusive.getPrevious(), + assertIgnored(range); + assertReplacedBranches(range.fromInclusive.getPrevious(), + expectedNewTargets); + } + + /** + *
      +	 * fun example(s: String?) = when (s) {
      +	 *     "a" -> "case a"
      +	 *     "b" -> "case b"
      +	 *     "c" -> "case c"
      +	 *     else -> "else"
      +	 * }
      +	 * 
      + */ + @Test + public void should_filter_Kotlin_nullable_else() { + 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 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.visitJumpInsn(Opcodes.IFNULL, caseElse); + m.visitVarInsn(Opcodes.ALOAD, 2); + 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(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); + } + + /** + *
      +	 * fun example(s: String?) = when (s) {
      +	 *     "a" -> "case a"
      +	 *     "b" -> "case b"
      +	 *     "c" -> "case c"
      +	 *     null -> "null"
      +	 *     else -> "else"
      +	 * }
      +	 * 
      + */ + @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).
    • From a685e56a199689d9bdfe9ffc85fc06fac551b32a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 22 Dec 2024 09:35:29 +0100 Subject: [PATCH 174/255] Use `Integer.valueOf` instead of deprecated constructor (#1826) --- .../src/org/jacoco/core/internal/analysis/CounterImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java index 6534afbb5a..752abb44e0 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java @@ -180,7 +180,7 @@ public void testEquals3() { @Test public void testEquals4() { ICounter c = CounterImpl.getInstance(300, 123); - assertFalse(c.equals(new Integer(123))); + assertFalse(c.equals(Integer.valueOf(123))); } @Test From f368aee3f4ee8abbd01a21b09eb7c7fc43298a32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 23:22:25 +0100 Subject: [PATCH 175/255] Bump actions/upload-artifact from 4.4.3 to 4.5.0 (#1830) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.3 to 4.5.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882...6f51ac03b9356f520e9adb1b1b7802705f340c2b) --- updated-dependencies: - dependency-name: actions/upload-artifact 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 089b7f2f39..a01734b624 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: ./mvnw -V -B -e --no-transfer-progress \ verify -Djdk.version=6 -Dbytecode.version=5 \ --toolchains=toolchains.xml - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 id: artifact-upload-step with: name: jacoco From f39a12843f75d42ad9334bcb77bc9c1c4e9de586 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 22:52:37 +0000 Subject: [PATCH 176/255] Bump actions/setup-java from 4.5.0 to 4.6.0 (#1829) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/8df1039502a15bceb9433410b1a100fbe190c53b...7a6d8a8234af8eb26422e24e3006232cccaa061b) --- 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 a01734b624..70b04e8987 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@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 + - uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.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@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 + - uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0 with: distribution: 'zulu' java-version: | From 4e159f7b351f8038bd72a0813445a427d62586b3 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Wed, 1 Jan 2025 21:57:35 +0100 Subject: [PATCH 177/255] Happy New Year 2025! --- LICENSE.md | 2 +- jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml | 2 +- .../it/it-check-fails-halt/src/main/java/Example.java | 2 +- .../it/it-check-fails-halt/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml | 2 +- .../it/it-check-fails-no-halt/src/main/java/Example.java | 2 +- .../it/it-check-fails-no-halt/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-check-fails-no-halt/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-check-passes/pom.xml | 2 +- .../it/it-check-passes/src/main/java/Example.java | 2 +- .../it/it-check-passes/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-check-passes/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-customize-agent/pom.xml | 2 +- .../it/it-customize-agent/src/main/java/Example.java | 2 +- .../it/it-customize-agent/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-dump/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-dump/src/main/java/Server.java | 2 +- jacoco-maven-plugin.test/it/it-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml | 2 +- .../src/main/java/org/project/DatabaseUtil.java | 2 +- .../src/main/java/org/project/FileUtil.java | 2 +- .../src/main/java/org/project/TestUtil.java | 2 +- .../src/test/java/org/project/TestDatabaseUtil.java | 2 +- jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh | 2 +- .../it/it-java9-offline-instrumentation/pom.xml | 2 +- .../src/main/java/module-info.java | 2 +- .../src/main/java/org/example/Example.java | 2 +- .../src/test/java/org/example/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-java9/pom.xml | 2 +- .../it/it-java9/src/main/java/Example.java | 2 +- .../it/it-java9/src/test/java/ExampleTest.java | 2 +- .../it/it-merge-passes/it-merge-passes-merge/pom.xml | 2 +- .../it/it-merge-passes/it-merge-passes-project1/pom.xml | 2 +- .../it-merge-passes-project1/src/main/java/Example.java | 2 +- .../it-merge-passes-project1/src/test/java/ExampleTest.java | 2 +- .../it/it-merge-passes/it-merge-passes-project2/pom.xml | 2 +- .../it-merge-passes-project2/src/main/java/Example.java | 2 +- .../it-merge-passes-project2/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-merge-passes/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh | 2 +- .../it/it-multi-module/child-jar-without-sources/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml | 2 +- .../it/it-multi-module/child/src/main/java/Example.java | 2 +- .../child/src/main/java/somepackage/Example.java | 2 +- .../it/it-multi-module/child/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-multi-module/pom.xml | 2 +- .../it/it-multi-module/skip-child/pom.xml | 2 +- .../it/it-multi-module/skip-child/src/test/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-multi-module/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml | 2 +- .../it/it-multiple-executions/src/main/java/Example.java | 2 +- .../it/it-multiple-executions/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-multiple-executions/verify.bsh | 2 +- .../child-without-main-classes/pom.xml | 2 +- .../child-without-main-classes/src/test/java/ExampleTest.java | 2 +- .../it/it-offline-instrumentation/child/pom.xml | 2 +- .../child/src/main/java/DoNotInstrument.java | 2 +- .../child/src/main/java/Example.java | 2 +- .../child/src/test/java/ExampleTest.java | 2 +- .../it/it-offline-instrumentation/pom.xml | 2 +- .../it/it-offline-instrumentation/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-prepend-property-skip/pom.xml | 2 +- .../it-prepend-property-skip/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-prepend-property/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh | 2 +- .../it/it-report-aggregate-customization/child1/pom.xml | 2 +- .../child1/src/main/java/package1/Example1.java | 2 +- .../child1/src/test/java/package1/Example1Test.java | 2 +- .../it/it-report-aggregate-customization/child2/pom.xml | 2 +- .../child2/src/main/java/package2/Example2.java | 2 +- .../child2/src/test/java/package2/Example2Test.java | 2 +- .../it/it-report-aggregate-customization/pom.xml | 2 +- .../it/it-report-aggregate-customization/report/pom.xml | 2 +- .../it/it-report-aggregate-customization/verify.bsh | 2 +- .../it/it-report-aggregate/child1-test/pom.xml | 2 +- .../child1-test/src/test/java/package1/Example1bTest.java | 2 +- .../it/it-report-aggregate/child1/pom.xml | 2 +- .../child1/src/main/java/package1/Example1a.java | 2 +- .../child1/src/main/java/package1/Example1b.java | 2 +- .../child1/src/test/java/package1/Example1aTest.java | 2 +- .../it/it-report-aggregate/child2/pom.xml | 2 +- .../child2/src/main/java/package2/Example2.java | 2 +- .../child2/src/test/java/package2/Example2Test.java | 2 +- .../it/it-report-aggregate/child2v2/pom.xml | 2 +- .../child2v2/src/main/java/package2/Example2.java | 2 +- .../child2v2/src/test/java/package2/Example2Test.java | 2 +- jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml | 2 +- .../it/it-report-aggregate/report/pom.xml | 2 +- .../report/src/test/java/packagereport/ReportTest.java | 2 +- jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml | 2 +- .../it/it-report-nomatch/src/main/java/Example.java | 2 +- jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-select-formats/pom.xml | 2 +- .../it/it-report-select-formats/src/main/java/Example.java | 2 +- .../it-report-select-formats/src/test/java/ExampleTest.java | 2 +- .../it/it-report-select-formats/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-unreadable-dump/pom.xml | 2 +- .../it/it-report-unreadable-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml | 2 +- .../it/it-report-without-debug/src/main/java/Example.java | 2 +- .../it/it-report-without-debug/src/test/java/ExampleTest.java | 2 +- .../it/it-report-without-debug/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml | 2 +- jacoco-maven-plugin.test/it/it-report-without-dump/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml | 2 +- .../it/it-site-failsafe/src/main/java/Example.java | 2 +- .../it/it-site-failsafe/src/test/java/ExampleIT.java | 2 +- .../it/it-site-failsafe/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh | 2 +- jacoco-maven-plugin.test/it/it-site/pom.xml | 2 +- .../it/it-site/src/main/java/Example.java | 2 +- .../it/it-site/src/test/java/ExampleTest.java | 2 +- jacoco-maven-plugin.test/it/it-site/verify.bsh | 2 +- jacoco-maven-plugin.test/it/settings.xml | 2 +- jacoco-maven-plugin.test/it/setup-parent/pom.xml | 2 +- jacoco-maven-plugin.test/pom.xml | 2 +- .../META-INF/m2e/lifecycle-mapping-metadata.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- .../src/org/jacoco/maven/AbstractAgentMojo.java | 2 +- .../src/org/jacoco/maven/AbstractJacocoMojo.java | 2 +- .../src/org/jacoco/maven/AbstractReportMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java | 2 +- .../src/org/jacoco/maven/ReportAggregateMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportFormat.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java | 2 +- jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java | 2 +- .../src/org/jacoco/maven/RuleConfiguration.java | 2 +- jacoco/assembly.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- .../src/org/jacoco/agent/rt/internal/AgentModuleTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/AgentTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java | 2 +- .../org/jacoco/agent/rt/internal/CoverageTransformerTest.java | 2 +- .../src/org/jacoco/agent/rt/internal/ExceptionRecorder.java | 2 +- .../org/jacoco/agent/rt/internal/output/ExecutorTestBase.java | 2 +- .../org/jacoco/agent/rt/internal/output/FileOutputTest.java | 2 +- .../org/jacoco/agent/rt/internal/output/MockServerSocket.java | 2 +- .../jacoco/agent/rt/internal/output/MockServerSocketTest.java | 2 +- .../jacoco/agent/rt/internal/output/MockSocketConnection.java | 2 +- .../agent/rt/internal/output/MockSocketConnectionTest.java | 2 +- .../jacoco/agent/rt/internal/output/TcpClientOutputTest.java | 2 +- .../jacoco/agent/rt/internal/output/TcpConnectionTest.java | 2 +- .../jacoco/agent/rt/internal/output/TcpServerOutputTest.java | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java | 2 +- org.jacoco.agent.rt/src/com/vladium/emma/rt/package-info.java | 2 +- org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java | 2 +- org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java | 2 +- .../src/org/jacoco/agent/rt/internal/Agent.java | 2 +- .../src/org/jacoco/agent/rt/internal/AgentModule.java | 2 +- .../src/org/jacoco/agent/rt/internal/ClassFileDumper.java | 2 +- .../src/org/jacoco/agent/rt/internal/ConfigLoader.java | 2 +- .../src/org/jacoco/agent/rt/internal/CoverageTransformer.java | 2 +- .../src/org/jacoco/agent/rt/internal/IExceptionLogger.java | 2 +- .../src/org/jacoco/agent/rt/internal/JmxRegistration.java | 2 +- .../src/org/jacoco/agent/rt/internal/Offline.java | 2 +- .../src/org/jacoco/agent/rt/internal/PreMain.java | 2 +- .../src/org/jacoco/agent/rt/internal/output/FileOutput.java | 2 +- .../src/org/jacoco/agent/rt/internal/output/IAgentOutput.java | 2 +- .../src/org/jacoco/agent/rt/internal/output/NoneOutput.java | 2 +- .../org/jacoco/agent/rt/internal/output/TcpClientOutput.java | 2 +- .../org/jacoco/agent/rt/internal/output/TcpConnection.java | 2 +- .../org/jacoco/agent/rt/internal/output/TcpServerOutput.java | 2 +- org.jacoco.agent.rt/src/org/jacoco/agent/rt/package-info.java | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent.test/src/org/jacoco/agent/AgentJarTest.java | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.agent/src/org/jacoco/agent/AgentJar.java | 2 +- org.jacoco.agent/src/org/jacoco/agent/package-info.java | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant.test/src/TestTargetInDefault.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml | 2 +- .../src/org/jacoco/ant/AntFilesLocatorTest.java | 2 +- .../src/org/jacoco/ant/AntResourcesLocatorTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java | 2 +- .../src/org/jacoco/ant/DumpExecClassNames.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml | 2 +- .../src/org/jacoco/ant/DumpTaskWithServerTest.java | 2 +- .../src/org/jacoco/ant/DumpTaskWithServerTest.xml | 2 +- .../src/org/jacoco/ant/IllegalReflectiveAccessTarget.java | 2 +- .../src/org/jacoco/ant/InstrumentTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java | 2 +- .../src/org/jacoco/ant/ReportTaskLocaleTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml | 2 +- .../src/org/jacoco/ant/SecurityManagerTest.java | 2 +- .../src/org/jacoco/ant/SecurityManagerTest.xml | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java | 2 +- org.jacoco.ant.test/src/org/jacoco/ant/empty.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AgentTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/DumpTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/MergeTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/ReportTask.java | 2 +- org.jacoco.ant/src/org/jacoco/ant/antlib.xml | 2 +- org.jacoco.build/pom.xml | 4 ++-- org.jacoco.cli.test/pom.xml | 2 +- .../src/org/jacoco/cli/internal/CommandTestBase.java | 2 +- org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java | 2 +- .../src/org/jacoco/cli/internal/XmlDocumentationTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ClassInfoTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/DumpTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ExecInfoTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/InstrumentTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/MergeTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/ReportTest.java | 2 +- .../src/org/jacoco/cli/internal/commands/VersionTest.java | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/Command.java | 2 +- .../src/org/jacoco/cli/internal/CommandHandler.java | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/CommandParser.java | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/Main.java | 2 +- .../src/org/jacoco/cli/internal/XmlDocumentation.java | 2 +- .../src/org/jacoco/cli/internal/commands/AllCommands.java | 2 +- .../src/org/jacoco/cli/internal/commands/ClassInfo.java | 2 +- org.jacoco.cli/src/org/jacoco/cli/internal/commands/Dump.java | 2 +- .../src/org/jacoco/cli/internal/commands/ExecInfo.java | 2 +- .../src/org/jacoco/cli/internal/commands/Instrument.java | 2 +- .../src/org/jacoco/cli/internal/commands/Merge.java | 2 +- .../src/org/jacoco/cli/internal/commands/Report.java | 2 +- .../src/org/jacoco/cli/internal/commands/Version.java | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- .../core/test/validation/groovy/GroovyAutoCloneClassTest.java | 2 +- .../validation/groovy/GroovyAutoExternalizeClassTest.java | 2 +- .../core/test/validation/groovy/GroovyBindableClassTest.java | 2 +- .../core/test/validation/groovy/GroovyBuilderClassTest.java | 2 +- .../core/test/validation/groovy/GroovyCanonicalClassTest.java | 2 +- .../core/test/validation/groovy/GroovyDelegateClassTest.java | 2 +- .../core/test/validation/groovy/GroovyImmutableClassTest.java | 2 +- .../test/validation/groovy/GroovyIndexPropertyClassTest.java | 2 +- .../core/test/validation/groovy/GroovySortableClassTest.java | 2 +- .../core/test/validation/groovy/GroovyVetoableClassTest.java | 2 +- .../groovy/targets/GroovyAutoCloneClassTarget.groovy | 2 +- .../groovy/targets/GroovyAutoExternalizeClassTarget.groovy | 2 +- .../groovy/targets/GroovyBindableClassTarget.groovy | 2 +- .../validation/groovy/targets/GroovyBuilderClassTarget.groovy | 2 +- .../groovy/targets/GroovyCanonicalClassTarget.groovy | 2 +- .../groovy/targets/GroovyDelegateClassTarget.groovy | 2 +- .../groovy/targets/GroovyImmutableClassTarget.groovy | 2 +- .../groovy/targets/GroovyIndexPropertyClassTarget.groovy | 2 +- .../groovy/targets/GroovySortableClassTarget.groovy | 2 +- .../groovy/targets/GroovyVetoableClassTarget.groovy | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- .../core/test/validation/java14/SwitchExpressionsTest.java | 2 +- .../validation/java14/targets/SwitchExpressionsTarget.java | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- .../jacoco/core/test/validation/java16/InstanceofTest.java | 2 +- .../org/jacoco/core/test/validation/java16/RecordsTest.java | 2 +- .../core/test/validation/java16/targets/InstanceofTarget.java | 2 +- .../core/test/validation/java16/targets/RecordsTarget.java | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- .../core/test/validation/java21/RecordPatternsTest.java | 2 +- .../test/validation/java21/SwitchPatternMatchingTest.java | 2 +- .../test/validation/java21/targets/RecordPatternsTarget.java | 2 +- .../java21/targets/SwitchPatternMatchingTarget.java | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- .../core/test/validation/java5/AnnotationGeneratedTest.java | 2 +- .../core/test/validation/java5/AnnotationInitializerTest.java | 2 +- .../src/org/jacoco/core/test/validation/java5/AssertTest.java | 2 +- .../jacoco/core/test/validation/java5/BadCycleClassTest.java | 2 +- .../core/test/validation/java5/BooleanExpressionsTest.java | 2 +- .../core/test/validation/java5/ClassInitializerTest.java | 2 +- .../jacoco/core/test/validation/java5/ConstructorsTest.java | 2 +- .../java5/ControlStructureBeforeSuperConstructorTest.java | 2 +- .../core/test/validation/java5/ControlStructuresTest.java | 2 +- .../core/test/validation/java5/CyclomaticComplexityTest.java | 2 +- .../core/test/validation/java5/EnumConstructorTest.java | 2 +- .../core/test/validation/java5/EnumImplicitMethodsTest.java | 2 +- .../org/jacoco/core/test/validation/java5/EnumSwitchTest.java | 2 +- .../org/jacoco/core/test/validation/java5/ExceptionsTest.java | 2 +- .../core/test/validation/java5/ExplicitInitialFrameTest.java | 2 +- .../java5/FieldInitializationInTwoConstructorsTest.java | 2 +- .../org/jacoco/core/test/validation/java5/FinallyTest.java | 2 +- .../src/org/jacoco/core/test/validation/java5/FramesTest.java | 2 +- .../validation/java5/ImplicitFieldInitializationTest.java | 2 +- .../test/validation/java5/InterfaceClassInitializerTest.java | 2 +- .../core/test/validation/java5/StructuredLockingTest.java | 2 +- .../jacoco/core/test/validation/java5/SynchronizedTest.java | 2 +- .../org/jacoco/core/test/validation/java5/SyntheticTest.java | 2 +- .../validation/java5/targets/AnnotationGeneratedTarget.java | 2 +- .../validation/java5/targets/AnnotationInitializerTarget.java | 2 +- .../core/test/validation/java5/targets/AssertTarget.java | 2 +- .../test/validation/java5/targets/BadCycleClassTarget.java | 2 +- .../validation/java5/targets/BooleanExpressionsTarget.java | 2 +- .../test/validation/java5/targets/ClassInitializerTarget.java | 2 +- .../test/validation/java5/targets/ConstructorsTarget.java | 2 +- .../targets/ControlStructureBeforeSuperConstructorTarget.java | 2 +- .../validation/java5/targets/ControlStructuresTarget.java | 2 +- .../test/validation/java5/targets/EnumConstructorTarget.java | 2 +- .../validation/java5/targets/EnumImplicitMethodsTarget.java | 2 +- .../core/test/validation/java5/targets/EnumSwitchTarget.java | 2 +- .../core/test/validation/java5/targets/ExceptionsTarget.java | 2 +- .../validation/java5/targets/ExplicitInitialFrameTarget.java | 2 +- .../targets/FieldInitializationInTwoConstructorsTarget.java | 2 +- .../core/test/validation/java5/targets/FinallyTarget.java | 2 +- .../java5/targets/ImplicitFieldInitializationTarget.java | 2 +- .../java5/targets/InterfaceClassInitializerTarget.java | 2 +- .../validation/java5/targets/StructuredLockingTarget.java | 2 +- .../test/validation/java5/targets/SynchronizedTarget.java | 2 +- .../core/test/validation/java5/targets/SyntheticTarget.java | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- .../jacoco/core/test/validation/java7/StringSwitchTest.java | 2 +- .../core/test/validation/java7/TryWithResourcesTest.java | 2 +- .../test/validation/java7/targets/StringSwitchTarget.java | 2 +- .../test/validation/java7/targets/TryWithResourcesTarget.java | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- .../test/validation/java8/AnnotationOnLocalVariableTest.java | 2 +- .../core/test/validation/java8/BadCycleInterfaceTest.java | 2 +- .../test/validation/java8/BootstrapMethodReferenceTest.java | 2 +- .../test/validation/java8/InterfaceDefaultMethodsTest.java | 2 +- .../validation/java8/InterfaceOnlyDefaultMethodsTest.java | 2 +- .../core/test/validation/java8/LambdaExpressionsTest.java | 2 +- .../core/test/validation/java8/LambdaInInterfaceTest.java | 2 +- .../core/test/validation/java8/LambdaSerializableTest.java | 2 +- .../java8/targets/AnnotationOnLocalVariableTarget.java | 2 +- .../validation/java8/targets/BadCycleInterfaceTarget.java | 2 +- .../java8/targets/InterfaceDefaultMethodsTarget.java | 2 +- .../java8/targets/InterfaceOnlyDefaultMethodsTarget.java | 2 +- .../validation/java8/targets/LambdaExpressionsTarget.java | 2 +- .../validation/java8/targets/LambdaInInterfaceTarget.java | 2 +- .../validation/java8/targets/LambdaSerializableTarget.java | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- .../test/validation/kotlin/KotlinCallableReferenceTest.java | 2 +- .../test/validation/kotlin/KotlinControlStructuresTest.java | 2 +- .../core/test/validation/kotlin/KotlinCoroutineTest.java | 2 +- .../core/test/validation/kotlin/KotlinCrossinlineTest.java | 2 +- .../core/test/validation/kotlin/KotlinDataClassTest.java | 2 +- .../test/validation/kotlin/KotlinDefaultArgumentsTest.java | 2 +- .../core/test/validation/kotlin/KotlinDefaultMethodsTest.java | 2 +- .../core/test/validation/kotlin/KotlinDelegatesTest.java | 2 +- .../core/test/validation/kotlin/KotlinElvisOperatorTest.java | 2 +- .../jacoco/core/test/validation/kotlin/KotlinEnumTest.java | 2 +- .../core/test/validation/kotlin/KotlinExceptionsTest.java | 2 +- .../core/test/validation/kotlin/KotlinInlineClassTest.java | 2 +- .../core/test/validation/kotlin/KotlinInlineReifiedTest.java | 2 +- .../jacoco/core/test/validation/kotlin/KotlinInlineTest.java | 2 +- .../core/test/validation/kotlin/KotlinJvmSyntheticTest.java | 2 +- .../test/validation/kotlin/KotlinLambdaExpressionsTest.java | 2 +- .../test/validation/kotlin/KotlinLambdaSerializableTest.java | 2 +- .../core/test/validation/kotlin/KotlinLateinitTest.java | 2 +- .../test/validation/kotlin/KotlinNotNullOperatorTest.java | 2 +- .../test/validation/kotlin/KotlinSafeCallOperatorTest.java | 2 +- .../core/test/validation/kotlin/KotlinSafeCastTest.java | 2 +- .../core/test/validation/kotlin/KotlinSynchronizedTest.java | 2 +- .../test/validation/kotlin/KotlinSyntheticAccessorsTest.java | 2 +- .../test/validation/kotlin/KotlinTopLevelFunctionTest.java | 2 +- .../test/validation/kotlin/KotlinUnsafeCastOperatorTest.java | 2 +- .../core/test/validation/kotlin/KotlinWhenEnumTest.java | 2 +- .../core/test/validation/kotlin/KotlinWhenSealedTest.java | 2 +- .../core/test/validation/kotlin/KotlinWhenStringTest.java | 2 +- .../kotlin/targets/KotlinCallableReferenceTarget.kt | 2 +- .../kotlin/targets/KotlinControlStructuresTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinCoroutineTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinCrossinlineTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinDataClassTarget.kt | 2 +- .../validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt | 2 +- .../validation/kotlin/targets/KotlinDefaultMethodsTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinDelegatesTarget.kt | 2 +- .../validation/kotlin/targets/KotlinElvisOperatorTarget.kt | 2 +- .../core/test/validation/kotlin/targets/KotlinEnumTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinExceptionsTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinInlineClassTarget.kt | 2 +- .../validation/kotlin/targets/KotlinInlineReifiedTarget.kt | 2 +- .../core/test/validation/kotlin/targets/KotlinInlineTarget.kt | 2 +- .../validation/kotlin/targets/KotlinJvmSyntheticTarget.kt | 2 +- .../kotlin/targets/KotlinLambdaExpressionsTarget.kt | 2 +- .../kotlin/targets/KotlinLambdaSerializableTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinLateinitTarget.kt | 2 +- .../validation/kotlin/targets/KotlinNotNullOperatorTarget.kt | 2 +- .../validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinSafeCastTarget.kt | 2 +- .../validation/kotlin/targets/KotlinSynchronizedTarget.kt | 2 +- .../kotlin/targets/KotlinSyntheticAccessorsTarget.kt | 2 +- .../validation/kotlin/targets/KotlinTopLevelFunctionTarget.kt | 2 +- .../kotlin/targets/KotlinUnsafeCastOperatorTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinWhenEnumTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinWhenSealedTarget.kt | 2 +- .../test/validation/kotlin/targets/KotlinWhenStringTarget.kt | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- .../test/validation/scala/ScalaAnonymousFunctionTest.java | 2 +- .../core/test/validation/scala/ScalaSingletonObjectTest.java | 2 +- .../core/test/validation/scala/ScalaSynchronizedTest.java | 2 +- .../scala/targets/ScalaAnonymousFunctionTarget.scala | 2 +- .../validation/scala/targets/ScalaSingletonObjectTarget.scala | 2 +- .../validation/scala/targets/ScalaSynchronizedTarget.scala | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java | 2 +- .../src/org/jacoco/core/analysis/AnalyzerTest.java | 2 +- .../src/org/jacoco/core/analysis/CounterComparatorTest.java | 2 +- .../src/org/jacoco/core/analysis/CoverageBuilderTest.java | 2 +- .../src/org/jacoco/core/analysis/CoverageNodeImplTest.java | 2 +- .../src/org/jacoco/core/analysis/NodeComparatorTest.java | 2 +- .../org/jacoco/core/data/ExecutionDataReaderWriterTest.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataStoreTest.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataTest.java | 2 +- .../core/data/IncompatibleExecDataVersionExceptionTest.java | 2 +- .../src/org/jacoco/core/data/SessionInfoStoreTest.java | 2 +- .../src/org/jacoco/core/data/SessionInfoTest.java | 2 +- .../src/org/jacoco/core/instr/ClassFileVersionsTest.java | 2 +- .../src/org/jacoco/core/instr/InstrumenterTest.java | 2 +- .../src/org/jacoco/core/instr/MethodRecorder.java | 2 +- .../src/org/jacoco/core/instr/ResizeInstructionsTest.java | 2 +- .../src/org/jacoco/core/internal/ContentTypeDetectorTest.java | 2 +- .../src/org/jacoco/core/internal/Pack200StreamsTest.java | 2 +- .../jacoco/core/internal/analysis/BundleCoverageImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/ClassAnalyzerTest.java | 2 +- .../jacoco/core/internal/analysis/ClassCoverageImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/CounterImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/InstructionTest.java | 2 +- .../core/internal/analysis/InstructionsBuilderTest.java | 2 +- .../src/org/jacoco/core/internal/analysis/LineImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/MethodAnalyzerTest.java | 2 +- .../core/internal/analysis/MethodCoverageCalculatorTest.java | 2 +- .../jacoco/core/internal/analysis/MethodCoverageImplTest.java | 2 +- .../jacoco/core/internal/analysis/PackageCoverageTest.java | 2 +- .../core/internal/analysis/SourceFileCoverageImplTest.java | 2 +- .../org/jacoco/core/internal/analysis/SourceNodeImplTest.java | 2 +- .../src/org/jacoco/core/internal/analysis/StringPoolTest.java | 2 +- .../core/internal/analysis/filter/AbstractMatcherTest.java | 2 +- .../analysis/filter/AnnotationGeneratedFilterTest.java | 2 +- .../core/internal/analysis/filter/AssertFilterTest.java | 2 +- .../core/internal/analysis/filter/BridgeFilterTest.java | 2 +- .../analysis/filter/EnumEmptyConstructorFilterTest.java | 2 +- .../jacoco/core/internal/analysis/filter/EnumFilterTest.java | 2 +- .../internal/analysis/filter/ExhaustiveSwitchFilterTest.java | 2 +- .../core/internal/analysis/filter/FilterContextMock.java | 2 +- .../jacoco/core/internal/analysis/filter/FilterTestBase.java | 2 +- .../core/internal/analysis/filter/FinallyFilterTest.java | 2 +- .../internal/analysis/filter/KotlinComposeFilterTest.java | 2 +- .../internal/analysis/filter/KotlinCoroutineFilterTest.java | 2 +- .../analysis/filter/KotlinDefaultArgumentsFilterTest.java | 2 +- .../analysis/filter/KotlinDefaultMethodsFilterTest.java | 2 +- .../core/internal/analysis/filter/KotlinEnumFilterTest.java | 2 +- .../internal/analysis/filter/KotlinGeneratedFilterTest.java | 2 +- .../internal/analysis/filter/KotlinInlineClassFilterTest.java | 2 +- .../core/internal/analysis/filter/KotlinInlineFilterTest.java | 2 +- .../internal/analysis/filter/KotlinLateinitFilterTest.java | 2 +- .../analysis/filter/KotlinNotNullOperatorFilterTest.java | 2 +- .../jacoco/core/internal/analysis/filter/KotlinSMAPTest.java | 2 +- .../analysis/filter/KotlinSafeCallOperatorFilterTest.java | 2 +- .../internal/analysis/filter/KotlinSyntheticFilterTest.java | 2 +- .../analysis/filter/KotlinUnsafeCastOperatorFilterTest.java | 2 +- .../core/internal/analysis/filter/KotlinWhenFilterTest.java | 2 +- .../internal/analysis/filter/KotlinWhenStringFilterTest.java | 2 +- .../filter/PrivateEmptyNoArgConstructorFilterTest.java | 2 +- .../internal/analysis/filter/RecordPatternFilterTest.java | 2 +- .../core/internal/analysis/filter/RecordsFilterTest.java | 2 +- .../core/internal/analysis/filter/StringSwitchFilterTest.java | 2 +- .../internal/analysis/filter/StringSwitchJavacFilterTest.java | 2 +- .../core/internal/analysis/filter/SynchronizedFilterTest.java | 2 +- .../core/internal/analysis/filter/SyntheticFilterTest.java | 2 +- .../analysis/filter/TryWithResourcesEcjFilterTest.java | 2 +- .../analysis/filter/TryWithResourcesJavac11FilterTest.java | 2 +- .../analysis/filter/TryWithResourcesJavacFilterTest.java | 2 +- .../src/org/jacoco/core/internal/data/CRC64Test.java | 2 +- .../jacoco/core/internal/data/CompactDataInputOutputTest.java | 2 +- .../org/jacoco/core/internal/flow/ClassProbesAdapterTest.java | 2 +- .../src/org/jacoco/core/internal/flow/FrameSnapshotTest.java | 2 +- .../org/jacoco/core/internal/flow/LabelFlowAnalyzerTest.java | 2 +- .../src/org/jacoco/core/internal/flow/LabelInfoTest.java | 2 +- .../jacoco/core/internal/flow/MethodProbesAdapterTest.java | 2 +- .../org/jacoco/core/internal/flow/MethodSanitizerTest.java | 2 +- .../core/internal/instr/ClassFieldProbeArrayStrategyTest.java | 2 +- .../org/jacoco/core/internal/instr/ClassInstrumenterTest.java | 2 +- .../core/internal/instr/CondyProbeArrayStrategyTest.java | 2 +- .../core/internal/instr/DuplicateFrameEliminatorTest.java | 2 +- .../src/org/jacoco/core/internal/instr/InstrSupportTest.java | 2 +- .../internal/instr/InterfaceFieldProbeArrayStrategyTest.java | 2 +- .../core/internal/instr/LocalProbeArrayStrategyTest.java | 2 +- .../jacoco/core/internal/instr/MethodInstrumenterTest.java | 2 +- .../core/internal/instr/NoneProbeArrayStrategyTest.java | 2 +- .../core/internal/instr/ProbeArrayStrategyFactoryTest.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeCounterTest.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeInserterTest.java | 2 +- .../src/org/jacoco/core/internal/instr/SafetySlotTest.java | 2 +- .../org/jacoco/core/internal/instr/SignatureRemoverTest.java | 2 +- .../org/jacoco/core/internal/instr/ZeroLineNumberTest.java | 2 +- .../src/org/jacoco/core/runtime/AgentOptionsTest.java | 2 +- .../src/org/jacoco/core/runtime/CommandLineSupportTest.java | 2 +- .../src/org/jacoco/core/runtime/InjectedClassRuntimeTest.java | 2 +- .../src/org/jacoco/core/runtime/LoggerRuntimeTest.java | 2 +- .../jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java | 2 +- .../runtime/OfflineInstrumentationAccessGeneratorTest.java | 2 +- .../jacoco/core/runtime/RemoteControlReaderWriterTest.java | 2 +- .../src/org/jacoco/core/runtime/RuntimeDataTest.java | 2 +- .../src/org/jacoco/core/runtime/RuntimeTestBase.java | 2 +- .../org/jacoco/core/runtime/SystemPropertiesRuntimeTest.java | 2 +- .../src/org/jacoco/core/runtime/TestStorage.java | 2 +- .../src/org/jacoco/core/runtime/WildcardMatcherTest.java | 2 +- .../src/org/jacoco/core/test/InstrumentingLoader.java | 2 +- .../src/org/jacoco/core/test/InstrumentingLoaderTest.java | 2 +- .../src/org/jacoco/core/test/TargetLoader.java | 2 +- .../src/org/jacoco/core/test/perf/AnalysisTimeScenario.java | 2 +- .../core/test/perf/ExecuteInstrumentedCodeScenario.java | 2 +- .../src/org/jacoco/core/test/perf/IPerfOutput.java | 2 +- .../src/org/jacoco/core/test/perf/IPerfScenario.java | 2 +- .../jacoco/core/test/perf/InstrumentationSizeSzenario.java | 2 +- .../jacoco/core/test/perf/InstrumentationTimeScenario.java | 2 +- .../src/org/jacoco/core/test/perf/PerfOutputWriter.java | 2 +- .../src/org/jacoco/core/test/perf/PerformanceSuite.java | 2 +- .../src/org/jacoco/core/test/perf/TimedScenario.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target01.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target02.java | 2 +- .../src/org/jacoco/core/test/perf/targets/Target03.java | 2 +- .../src/org/jacoco/core/test/validation/Compiler.java | 2 +- .../src/org/jacoco/core/test/validation/JavaVersion.java | 2 +- .../src/org/jacoco/core/test/validation/JavaVersionTest.java | 2 +- .../src/org/jacoco/core/test/validation/Source.java | 2 +- .../src/org/jacoco/core/test/validation/SourceTest.java | 2 +- .../org/jacoco/core/test/validation/StatementExecutor.java | 2 +- .../jacoco/core/test/validation/StatementExecutorTest.java | 2 +- .../src/org/jacoco/core/test/validation/StatementParser.java | 2 +- .../org/jacoco/core/test/validation/StatementParserTest.java | 2 +- .../org/jacoco/core/test/validation/ValidationTestBase.java | 2 +- .../src/org/jacoco/core/test/validation/targets/Stubs.java | 2 +- .../src/org/jacoco/core/tools/ExecDumpClientTest.java | 2 +- .../src/org/jacoco/core/tools/ExecFileLoaderTest.java | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.core/src/org/jacoco/core/JaCoCo.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java | 2 +- .../src/org/jacoco/core/analysis/CounterComparator.java | 2 +- .../src/org/jacoco/core/analysis/CoverageBuilder.java | 2 +- .../src/org/jacoco/core/analysis/CoverageNodeImpl.java | 2 +- .../src/org/jacoco/core/analysis/IBundleCoverage.java | 2 +- .../src/org/jacoco/core/analysis/IClassCoverage.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java | 2 +- .../src/org/jacoco/core/analysis/ICoverageNode.java | 2 +- .../src/org/jacoco/core/analysis/ICoverageVisitor.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/ILine.java | 2 +- .../src/org/jacoco/core/analysis/IMethodCoverage.java | 2 +- .../src/org/jacoco/core/analysis/IPackageCoverage.java | 2 +- .../src/org/jacoco/core/analysis/ISourceFileCoverage.java | 2 +- org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java | 2 +- .../src/org/jacoco/core/analysis/NodeComparator.java | 2 +- .../src/org/jacoco/core/analysis/package-info.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataReader.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataStore.java | 2 +- .../src/org/jacoco/core/data/ExecutionDataWriter.java | 2 +- .../src/org/jacoco/core/data/IExecutionDataVisitor.java | 2 +- .../src/org/jacoco/core/data/ISessionInfoVisitor.java | 2 +- .../core/data/IncompatibleExecDataVersionException.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java | 2 +- .../src/org/jacoco/core/data/SessionInfoStore.java | 2 +- org.jacoco.core/src/org/jacoco/core/data/package-info.java | 2 +- org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java | 2 +- org.jacoco.core/src/org/jacoco/core/instr/package-info.java | 2 +- .../src/org/jacoco/core/internal/ContentTypeDetector.java | 2 +- .../src/org/jacoco/core/internal/InputStreams.java | 2 +- .../src/org/jacoco/core/internal/Pack200Streams.java | 2 +- .../org/jacoco/core/internal/analysis/BundleCoverageImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/ClassAnalyzer.java | 2 +- .../org/jacoco/core/internal/analysis/ClassCoverageImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/CounterImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/Instruction.java | 2 +- .../jacoco/core/internal/analysis/InstructionsBuilder.java | 2 +- .../src/org/jacoco/core/internal/analysis/LineImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/MethodAnalyzer.java | 2 +- .../core/internal/analysis/MethodCoverageCalculator.java | 2 +- .../org/jacoco/core/internal/analysis/MethodCoverageImpl.java | 2 +- .../jacoco/core/internal/analysis/PackageCoverageImpl.java | 2 +- .../jacoco/core/internal/analysis/SourceFileCoverageImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/SourceNodeImpl.java | 2 +- .../src/org/jacoco/core/internal/analysis/StringPool.java | 2 +- .../jacoco/core/internal/analysis/filter/AbstractMatcher.java | 2 +- .../internal/analysis/filter/AnnotationGeneratedFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/AssertFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/BridgeFilter.java | 2 +- .../internal/analysis/filter/EnumEmptyConstructorFilter.java | 2 +- .../org/jacoco/core/internal/analysis/filter/EnumFilter.java | 2 +- .../core/internal/analysis/filter/ExhaustiveSwitchFilter.java | 2 +- .../org/jacoco/core/internal/analysis/filter/FilterSet.java | 2 +- .../src/org/jacoco/core/internal/analysis/filter/Filters.java | 2 +- .../jacoco/core/internal/analysis/filter/FinallyFilter.java | 2 +- .../src/org/jacoco/core/internal/analysis/filter/IFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/IFilterContext.java | 2 +- .../jacoco/core/internal/analysis/filter/IFilterOutput.java | 2 +- .../core/internal/analysis/filter/KotlinComposeFilter.java | 2 +- .../core/internal/analysis/filter/KotlinCoroutineFilter.java | 2 +- .../analysis/filter/KotlinDefaultArgumentsFilter.java | 2 +- .../internal/analysis/filter/KotlinDefaultMethodsFilter.java | 2 +- .../core/internal/analysis/filter/KotlinEnumFilter.java | 2 +- .../core/internal/analysis/filter/KotlinGeneratedFilter.java | 2 +- .../internal/analysis/filter/KotlinInlineClassFilter.java | 2 +- .../core/internal/analysis/filter/KotlinInlineFilter.java | 2 +- .../core/internal/analysis/filter/KotlinLateinitFilter.java | 2 +- .../internal/analysis/filter/KotlinNotNullOperatorFilter.java | 2 +- .../org/jacoco/core/internal/analysis/filter/KotlinSMAP.java | 2 +- .../analysis/filter/KotlinSafeCallOperatorFilter.java | 2 +- .../analysis/filter/KotlinSyntheticAccessorsFilter.java | 2 +- .../analysis/filter/KotlinUnsafeCastOperatorFilter.java | 2 +- .../core/internal/analysis/filter/KotlinWhenFilter.java | 2 +- .../core/internal/analysis/filter/KotlinWhenStringFilter.java | 2 +- .../analysis/filter/PrivateEmptyNoArgConstructorFilter.java | 2 +- .../core/internal/analysis/filter/RecordPatternFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/RecordsFilter.java | 2 +- .../core/internal/analysis/filter/StringSwitchFilter.java | 2 +- .../internal/analysis/filter/StringSwitchJavacFilter.java | 2 +- .../core/internal/analysis/filter/SynchronizedFilter.java | 2 +- .../jacoco/core/internal/analysis/filter/SyntheticFilter.java | 2 +- .../internal/analysis/filter/TryWithResourcesEcjFilter.java | 2 +- .../analysis/filter/TryWithResourcesJavac11Filter.java | 2 +- .../internal/analysis/filter/TryWithResourcesJavacFilter.java | 2 +- org.jacoco.core/src/org/jacoco/core/internal/data/CRC64.java | 2 +- .../src/org/jacoco/core/internal/data/CompactDataInput.java | 2 +- .../src/org/jacoco/core/internal/data/CompactDataOutput.java | 2 +- .../src/org/jacoco/core/internal/flow/ClassProbesAdapter.java | 2 +- .../src/org/jacoco/core/internal/flow/ClassProbesVisitor.java | 2 +- .../src/org/jacoco/core/internal/flow/FrameSnapshot.java | 2 +- org.jacoco.core/src/org/jacoco/core/internal/flow/IFrame.java | 2 +- .../src/org/jacoco/core/internal/flow/IProbeIdGenerator.java | 2 +- .../src/org/jacoco/core/internal/flow/LabelFlowAnalyzer.java | 2 +- .../src/org/jacoco/core/internal/flow/LabelInfo.java | 2 +- .../org/jacoco/core/internal/flow/MethodProbesAdapter.java | 2 +- .../org/jacoco/core/internal/flow/MethodProbesVisitor.java | 2 +- .../src/org/jacoco/core/internal/flow/MethodSanitizer.java | 2 +- .../core/internal/instr/ClassFieldProbeArrayStrategy.java | 2 +- .../src/org/jacoco/core/internal/instr/ClassInstrumenter.java | 2 +- .../jacoco/core/internal/instr/CondyProbeArrayStrategy.java | 2 +- .../jacoco/core/internal/instr/DuplicateFrameEliminator.java | 2 +- .../org/jacoco/core/internal/instr/IProbeArrayStrategy.java | 2 +- .../src/org/jacoco/core/internal/instr/IProbeInserter.java | 2 +- .../src/org/jacoco/core/internal/instr/InstrSupport.java | 2 +- .../core/internal/instr/InterfaceFieldProbeArrayStrategy.java | 2 +- .../jacoco/core/internal/instr/LocalProbeArrayStrategy.java | 2 +- .../org/jacoco/core/internal/instr/MethodInstrumenter.java | 2 +- .../jacoco/core/internal/instr/NoneProbeArrayStrategy.java | 2 +- .../jacoco/core/internal/instr/ProbeArrayStrategyFactory.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeCounter.java | 2 +- .../src/org/jacoco/core/internal/instr/ProbeInserter.java | 2 +- .../src/org/jacoco/core/internal/instr/SignatureRemover.java | 2 +- org.jacoco.core/src/org/jacoco/core/package-info.java | 2 +- .../src/org/jacoco/core/runtime/AbstractRuntime.java | 2 +- org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java | 2 +- .../src/org/jacoco/core/runtime/CommandLineSupport.java | 2 +- .../jacoco/core/runtime/IExecutionDataAccessorGenerator.java | 2 +- .../src/org/jacoco/core/runtime/IRemoteCommandVisitor.java | 2 +- org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java | 2 +- .../src/org/jacoco/core/runtime/InjectedClassRuntime.java | 2 +- .../src/org/jacoco/core/runtime/LoggerRuntime.java | 2 +- .../org/jacoco/core/runtime/ModifiedSystemClassRuntime.java | 2 +- .../core/runtime/OfflineInstrumentationAccessGenerator.java | 2 +- .../src/org/jacoco/core/runtime/RemoteControlReader.java | 2 +- .../src/org/jacoco/core/runtime/RemoteControlWriter.java | 2 +- org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java | 2 +- .../src/org/jacoco/core/runtime/SystemPropertiesRuntime.java | 2 +- .../src/org/jacoco/core/runtime/WildcardMatcher.java | 2 +- org.jacoco.core/src/org/jacoco/core/runtime/package-info.java | 2 +- org.jacoco.core/src/org/jacoco/core/tools/ExecDumpClient.java | 2 +- org.jacoco.core/src/org/jacoco/core/tools/ExecFileLoader.java | 2 +- org.jacoco.core/src/org/jacoco/core/tools/package-info.java | 2 +- org.jacoco.doc/pom.xml | 2 +- org.jacoco.doc/xsl/cli.xsl | 2 +- org.jacoco.doc/xsl/maven-goal.xsl | 2 +- org.jacoco.examples.test/pom.xml | 2 +- .../src/org/jacoco/examples/ClassInfoTest.java | 2 +- .../src/org/jacoco/examples/ConsoleOutput.java | 2 +- .../src/org/jacoco/examples/CoreTutorialTest.java | 2 +- .../src/org/jacoco/examples/ExecDumpTest.java | 2 +- .../src/org/jacoco/examples/MBeanClientTest.java | 2 +- org.jacoco.examples.test/src/test/resources/verify-it.bsh | 2 +- .../src/test/resources/verify-offline.bsh | 2 +- org.jacoco.examples.test/src/test/resources/verify.bsh | 2 +- org.jacoco.examples/assembly.xml | 2 +- org.jacoco.examples/build/build-offline.xml | 2 +- org.jacoco.examples/build/build.xml | 2 +- org.jacoco.examples/build/pom-it.xml | 2 +- org.jacoco.examples/build/pom-offline.xml | 2 +- org.jacoco.examples/build/pom.xml | 2 +- .../src/main/java/org/jacoco/examples/expressions/Add.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Const.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Div.java | 2 +- .../java/org/jacoco/examples/expressions/IExpression.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Mul.java | 2 +- .../src/main/java/org/jacoco/examples/expressions/Sub.java | 2 +- .../java/org/jacoco/examples/parser/ExpressionParser.java | 2 +- .../build/src/main/java/org/jacoco/examples/parser/Main.java | 2 +- .../java/org/jacoco/examples/parser/ExpressionParserIT.java | 2 +- .../java/org/jacoco/examples/parser/ExpressionParserTest.java | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java | 2 +- org.jacoco.examples/src/org/jacoco/examples/CoreTutorial.java | 2 +- org.jacoco.examples/src/org/jacoco/examples/ExecDump.java | 2 +- .../src/org/jacoco/examples/ExecutionDataClient.java | 2 +- .../src/org/jacoco/examples/ExecutionDataServer.java | 2 +- org.jacoco.examples/src/org/jacoco/examples/MBeanClient.java | 2 +- .../src/org/jacoco/examples/ReportGenerator.java | 2 +- org.jacoco.report.test/pom.xml | 2 +- .../src/org/jacoco/report/DirectorySourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/FileMultiReportOutputTest.java | 2 +- .../org/jacoco/report/InputStreamSourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/JavaNamesTest.java | 2 +- .../src/org/jacoco/report/MemoryMultiReportOutput.java | 2 +- .../src/org/jacoco/report/MemoryOutput.java | 2 +- .../src/org/jacoco/report/MultiReportVisitorTest.java | 2 +- .../src/org/jacoco/report/MultiSourceFileLocatorTest.java | 2 +- .../src/org/jacoco/report/ReportStructureTestDriver.java | 2 +- .../src/org/jacoco/report/ZipMultiReportOutputTest.java | 2 +- .../src/org/jacoco/report/check/BundleCheckerTest.java | 2 +- .../src/org/jacoco/report/check/LimitTest.java | 2 +- .../src/org/jacoco/report/check/RuleTest.java | 2 +- .../src/org/jacoco/report/check/RulesCheckerTest.java | 2 +- .../src/org/jacoco/report/csv/CSVFormatterTest.java | 2 +- .../src/org/jacoco/report/csv/CSVGroupHandlerTest.java | 2 +- .../src/org/jacoco/report/csv/ClassRowWriterTest.java | 2 +- .../src/org/jacoco/report/csv/DelimitedWriterTest.java | 2 +- .../src/org/jacoco/report/html/HTMLFormatterTest.java | 2 +- .../org/jacoco/report/internal/NormalizedFileNamesTest.java | 2 +- .../org/jacoco/report/internal/ReportOutputFolderTest.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLElementTest.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLSupport.java | 2 +- .../src/org/jacoco/report/internal/html/LinkableStub.java | 2 +- .../org/jacoco/report/internal/html/page/BundlePageTest.java | 2 +- .../org/jacoco/report/internal/html/page/ClassPageTest.java | 2 +- .../org/jacoco/report/internal/html/page/MethodItemTest.java | 2 +- .../org/jacoco/report/internal/html/page/NodePageTest.java | 2 +- .../org/jacoco/report/internal/html/page/PackagePageTest.java | 2 +- .../report/internal/html/page/PackageSourcePageTest.java | 2 +- .../org/jacoco/report/internal/html/page/PageTestBase.java | 2 +- .../org/jacoco/report/internal/html/page/ReportPageTest.java | 2 +- .../jacoco/report/internal/html/page/SessionsPageTest.java | 2 +- .../jacoco/report/internal/html/page/SourceFilePageTest.java | 2 +- .../report/internal/html/page/SourceHighlighterTest.java | 2 +- .../jacoco/report/internal/html/resources/ResourcesTest.java | 2 +- .../org/jacoco/report/internal/html/resources/StylesTest.java | 2 +- .../org/jacoco/report/internal/html/table/BarColumnTest.java | 2 +- .../jacoco/report/internal/html/table/CounterColumnTest.java | 2 +- .../jacoco/report/internal/html/table/LabelColumnTest.java | 2 +- .../report/internal/html/table/PercentageColumnTest.java | 2 +- .../org/jacoco/report/internal/html/table/SortIndexTest.java | 2 +- .../src/org/jacoco/report/internal/html/table/TableTest.java | 2 +- .../org/jacoco/report/internal/xml/LocalEntityResolver.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLElementTest.java | 2 +- .../org/jacoco/report/internal/xml/XMLGroupVisitorTest.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLSupport.java | 2 +- .../src/org/jacoco/report/xml/XMLFormatterTest.java | 2 +- org.jacoco.report/pom.xml | 2 +- .../src/org/jacoco/report/DirectorySourceFileLocator.java | 2 +- .../src/org/jacoco/report/FileMultiReportOutput.java | 2 +- org.jacoco.report/src/org/jacoco/report/ILanguageNames.java | 2 +- .../src/org/jacoco/report/IMultiReportOutput.java | 2 +- .../src/org/jacoco/report/IReportGroupVisitor.java | 2 +- org.jacoco.report/src/org/jacoco/report/IReportVisitor.java | 2 +- .../src/org/jacoco/report/ISourceFileLocator.java | 2 +- .../src/org/jacoco/report/InputStreamSourceFileLocator.java | 2 +- org.jacoco.report/src/org/jacoco/report/JavaNames.java | 2 +- .../src/org/jacoco/report/MultiReportVisitor.java | 2 +- .../src/org/jacoco/report/MultiSourceFileLocator.java | 2 +- .../src/org/jacoco/report/ZipMultiReportOutput.java | 2 +- .../src/org/jacoco/report/check/BundleChecker.java | 2 +- .../src/org/jacoco/report/check/IViolationsOutput.java | 2 +- org.jacoco.report/src/org/jacoco/report/check/Limit.java | 2 +- org.jacoco.report/src/org/jacoco/report/check/Rule.java | 2 +- .../src/org/jacoco/report/check/RulesChecker.java | 2 +- .../src/org/jacoco/report/check/package-info.java | 2 +- org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java | 2 +- .../src/org/jacoco/report/csv/CSVGroupHandler.java | 2 +- .../src/org/jacoco/report/csv/ClassRowWriter.java | 2 +- .../src/org/jacoco/report/csv/DelimitedWriter.java | 2 +- org.jacoco.report/src/org/jacoco/report/csv/package-info.java | 2 +- .../src/org/jacoco/report/html/HTMLFormatter.java | 2 +- .../src/org/jacoco/report/html/package-info.java | 2 +- .../src/org/jacoco/report/internal/AbstractGroupVisitor.java | 2 +- .../src/org/jacoco/report/internal/NormalizedFileNames.java | 2 +- .../src/org/jacoco/report/internal/ReportOutputFolder.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLElement.java | 2 +- .../src/org/jacoco/report/internal/html/HTMLGroupVisitor.java | 2 +- .../org/jacoco/report/internal/html/IHTMLReportContext.java | 2 +- .../src/org/jacoco/report/internal/html/ILinkable.java | 2 +- .../org/jacoco/report/internal/html/index/ElementIndex.java | 2 +- .../org/jacoco/report/internal/html/index/IIndexUpdate.java | 2 +- .../org/jacoco/report/internal/html/index/package-info.java | 2 +- .../src/org/jacoco/report/internal/html/page/BundlePage.java | 2 +- .../src/org/jacoco/report/internal/html/page/ClassPage.java | 2 +- .../src/org/jacoco/report/internal/html/page/GroupPage.java | 2 +- .../src/org/jacoco/report/internal/html/page/MethodItem.java | 2 +- .../src/org/jacoco/report/internal/html/page/NodePage.java | 2 +- .../src/org/jacoco/report/internal/html/page/PackagePage.java | 2 +- .../jacoco/report/internal/html/page/PackageSourcePage.java | 2 +- .../src/org/jacoco/report/internal/html/page/ReportPage.java | 2 +- .../org/jacoco/report/internal/html/page/SessionsPage.java | 2 +- .../org/jacoco/report/internal/html/page/SourceFileItem.java | 2 +- .../org/jacoco/report/internal/html/page/SourceFilePage.java | 2 +- .../jacoco/report/internal/html/page/SourceHighlighter.java | 2 +- .../src/org/jacoco/report/internal/html/page/TablePage.java | 2 +- .../org/jacoco/report/internal/html/resources/Resources.java | 2 +- .../src/org/jacoco/report/internal/html/resources/Styles.java | 2 +- .../jacoco/report/internal/html/resources/package-info.java | 2 +- .../src/org/jacoco/report/internal/html/resources/sort.js | 2 +- .../src/org/jacoco/report/internal/html/table/BarColumn.java | 2 +- .../org/jacoco/report/internal/html/table/CounterColumn.java | 2 +- .../jacoco/report/internal/html/table/IColumnRenderer.java | 2 +- .../src/org/jacoco/report/internal/html/table/ITableItem.java | 2 +- .../org/jacoco/report/internal/html/table/LabelColumn.java | 2 +- .../jacoco/report/internal/html/table/PercentageColumn.java | 2 +- .../src/org/jacoco/report/internal/html/table/SortIndex.java | 2 +- .../src/org/jacoco/report/internal/html/table/Table.java | 2 +- .../report/internal/html/table/TableItemComparator.java | 2 +- .../org/jacoco/report/internal/html/table/package-info.java | 2 +- .../src/org/jacoco/report/internal/xml/ReportElement.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLCoverageWriter.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLElement.java | 2 +- .../src/org/jacoco/report/internal/xml/XMLGroupVisitor.java | 2 +- org.jacoco.report/src/org/jacoco/report/package-info.java | 2 +- org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java | 2 +- org.jacoco.report/src/org/jacoco/report/xml/package-info.java | 2 +- org.jacoco.report/src/org/jacoco/report/xml/report.dtd | 2 +- org.jacoco.tests/pom.xml | 2 +- 834 files changed, 835 insertions(+), 835 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 0c2e74523f..50688de56c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ License ======= -Copyright (c) 2009, 2024 Mountainminds GmbH & Co. KG and Contributors +Copyright (c) 2009, 2025 Mountainminds GmbH & Co. KG and Contributors The JaCoCo Java Code Coverage Library and all included documentation is made available by Mountainminds GmbH & Co. KG, Munich. Except indicated below, the diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml index 2b58a34d1d..81656f0df3 100644 --- a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml +++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml @@ -1,6 +1,6 @@ ../org.jacoco.core.test.validation.java7 ../org.jacoco.core.test.validation.java8 ../org.jacoco.core.test.validation.java14 From 5ee4222067c261a0de17888b1236f004ac2b21e1 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:59:55 +0100 Subject: [PATCH 191/255] Add validation test for `@JvmName` in Kotlin (#1842) --- .../validation/kotlin/KotlinJvmNameTest.java | 27 +++++++++++++++++++ .../kotlin/targets/KotlinJvmNameTarget.kt | 21 +++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmNameTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmNameTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmNameTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmNameTest.java new file mode 100644 index 0000000000..4117fab294 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinJvmNameTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinJvmNameTarget; + +/** + * Test of code coverage in {@link KotlinJvmNameTarget}. + */ +public class KotlinJvmNameTest extends ValidationTestBase { + + public KotlinJvmNameTest() { + super(KotlinJvmNameTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmNameTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmNameTarget.kt new file mode 100644 index 0000000000..b647a2a27e --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmNameTarget.kt @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 + * + *******************************************************************************/ +@file:JvmName("KotlinJvmNameTarget") + +package org.jacoco.core.test.validation.kotlin.targets + +import org.jacoco.core.test.validation.targets.Stubs.nop + +fun main(args: Array) { + nop() // assertFullyCovered() +} From c2596680f89fa1c1b66095a3d9e73cfe748a4a4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:43:06 +0000 Subject: [PATCH 192/255] Bump actions/setup-java from 4.6.0 to 4.7.0 (#1847) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/7a6d8a8234af8eb26422e24e3006232cccaa061b...3a4f6e1af504cf6a31855fa899c6aa5355ba6c12) --- 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 06688790e3..034c2ec01a 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@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0 + - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.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@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0 + - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 with: distribution: 'zulu' java-version: | From 0bb8bd525f22c6d2427c3b5e23b0292ec64201b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 09:41:52 +0100 Subject: [PATCH 193/255] Bump actions/upload-artifact from 4.6.0 to 4.6.1 (#1852) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08...4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1) --- 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 034c2ec01a..3650c2907e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: ./mvnw -V -B -e --no-transfer-progress \ verify -Djdk.version=6 -Dbytecode.version=5 \ --toolchains=toolchains.xml - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 id: artifact-upload-step with: name: jacoco From 80ebc77eaee121bfef3f132fdc4c9baa66137f0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:28:40 +0100 Subject: [PATCH 194/255] Upgrade maven-clean-plugin to 3.4.1 (#1850) --- 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 4b3816d68b..66369992cd 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -307,7 +307,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.4.0 + 3.4.1 org.apache.maven.plugins From c7da68b0f15e7cfc8482e7b524751401abd9b1e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 20:08:13 +0100 Subject: [PATCH 195/255] Upgrade maven-install-plugin to 3.1.4 (#1853) --- 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 66369992cd..545eb861ed 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -333,7 +333,7 @@ org.apache.maven.plugins maven-install-plugin - 3.1.3 + 3.1.4 org.apache.maven.plugins From 21f6a99d7bbd518b22838855c93af9ad72ff36fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 19:53:15 +0000 Subject: [PATCH 196/255] Upgrade maven-deploy-plugin to 3.1.4 (#1854) --- 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 545eb861ed..cf114eb0bb 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -323,7 +323,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.3 + 3.1.4 org.apache.maven.plugins From 99707c3b2d540285b4418a9d056bba5ee18453e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 22:43:06 +0100 Subject: [PATCH 197/255] Upgrade spotless-maven-plugin to 2.44.3 (#1851) --- 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 cf114eb0bb..537be728bd 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.44.2 + 2.44.3 org.sonarsource.scanner.maven From f0dcc6b0b78b04dd94617707551f6c2d18426d09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 14:06:54 +0100 Subject: [PATCH 198/255] Bump actions/upload-artifact from 4.6.1 to 4.6.2 (#1861) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.1 to 4.6.2. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1...ea165f8d65b6e75b540449e92b4886f43607fa02) --- 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 3650c2907e..e3c8ef4c7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: ./mvnw -V -B -e --no-transfer-progress \ verify -Djdk.version=6 -Dbytecode.version=5 \ --toolchains=toolchains.xml - - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 id: artifact-upload-step with: name: jacoco From ee07ecb663f256930aa3b12771855ff555ec4e1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 00:14:40 +0100 Subject: [PATCH 199/255] Upgrade Kotlin to 2.1.20 (#1860) --- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 7faa2f8f9d..1933228e2d 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.1.10 + 2.1.20 From 17d31aa1073b1a327f1d7b631ff480a60cd40df5 Mon Sep 17 00:00:00 2001 From: Ed Merks Date: Tue, 1 Apr 2025 00:35:56 +0200 Subject: [PATCH 200/255] Upgrade ASM to 9.8 (#1863) --- org.jacoco.build/licenses/{asm-9.7.1.html => asm-9.8.html} | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename org.jacoco.build/licenses/{asm-9.7.1.html => asm-9.8.html} (96%) diff --git a/org.jacoco.build/licenses/asm-9.7.1.html b/org.jacoco.build/licenses/asm-9.8.html similarity index 96% rename from org.jacoco.build/licenses/asm-9.7.1.html rename to org.jacoco.build/licenses/asm-9.8.html index 5aeeb0b5be..f74f83dc13 100644 --- a/org.jacoco.build/licenses/asm-9.7.1.html +++ b/org.jacoco.build/licenses/asm-9.8.html @@ -1,7 +1,7 @@

      ASM

      - ASM 9.7 is subject to the terms and + ASM 9.8 is subject to the terms and conditions of the following license:

      diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 537be728bd..c9d0738d86 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -139,7 +139,7 @@ ${jvm.args} - 9.7.1 + 9.8 1.9.16 2.0.28 4.13.2 diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 1a43306989..6c5c69cf72 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -80,8 +80,8 @@

      Non-functional Changes

      (GitHub #1708, #1707, #1681). -
    • JaCoCo now depends on ASM 9.7.1 - (GitHub #1739).
    • +
    • JaCoCo now depends on ASM 9.8 + (GitHub #1862).
    • More context information when IllegalArgumentException occurs during reading of zip file (GitHub #1833).
    • From e579092d415247939c7098bfbaa3cbbe4dc7fe0d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 1 Apr 2025 23:18:58 +0200 Subject: [PATCH 201/255] Happy birthday Java 24! (#1867) --- org.jacoco.doc/docroot/doc/changes.html | 12 ++++++------ org.jacoco.doc/docroot/doc/environment.html | 2 +- org.jacoco.doc/docroot/doc/faq.html | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 6c5c69cf72..389c8a4290 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,8 +22,12 @@

      Snapshot Build @qualified.bundle.version@ (@build.date@)

      New Features

        -
      • JaCoCo now officially supports Java 23 - (GitHub #1757).
      • +
      • JaCoCo now officially supports Java 23 and Java 24 + (GitHub #1757, + #1631, + #1867).
      • +
      • Experimental support for Java 25 class files + (GitHub #1807).
      • Calculation of line coverage for Kotlin inline functions (GitHub #1670).
      • Calculation of line coverage for Kotlin inline functions @@ -32,10 +36,6 @@

        New Features

        #1700).
      • Calculation of coverage for Kotlin JvmSynthetic functions (GitHub #1700).
      • -
      • Experimental support for Java 24 class files - (GitHub #1631).
      • -
      • Experimental support for Java 25 class files - (GitHub #1807).
      • Part of bytecode generated by the Kotlin Compose compiler plugin is filtered out during generation of report (GitHub #1616).
      • diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html index 0bbb5c6d69..f56639a9bc 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, 22 and 23 JDKs. + 18, 19, 20, 21, 22, 23, 24 and 25 JDKs.

        Build

        diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html index 27c5cae347..afa6d507c7 100644 --- a/org.jacoco.doc/docroot/doc/faq.html +++ b/org.jacoco.doc/docroot/doc/faq.html @@ -45,8 +45,8 @@

        Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?

        What Java versions are supported by JaCoCo?

        - 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. + JaCoCo officially supports Java class files from version 1.0 to 24. Also + experimental support for class files of version 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. From 78d5eff856bbe6129f05012e40c13d1840e20598 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Tue, 1 Apr 2025 23:12:04 +0200 Subject: [PATCH 202/255] Prepare release 0.8.13 --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 +- org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index 133b9d6fcd..0f8d9a06db 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index 31bea49086..fa660549d9 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index 3112beb77d..0f0da04b2d 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index 109cdbb6d1..5cd18fa386 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index 13c874308c..8de9b8e89e 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index 08bb758910..f7902c5284 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index 1a2bcada17..7d70fb756d 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index 0b45e2b634..8e3dec25b1 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index f5546815a0..6c6250c85b 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index c9d0738d86..0413ac4f1e 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index c425cc361f..bdba3be214 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 65745da5d8..6ecb2355ca 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index d6af226997..e278afda7b 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index 4794f349b7..ed0c115355 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index 49bfc1304e..d0521ec58c 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index 6c06a3b633..dd00a524c3 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index a7c0e7bcca..a1897ec9e9 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 4cd65d6e54..764971363e 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index 5cbac0fd73..10f7f26a4c 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 1933228e2d..0e8a13a063 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index d8a56fd7d0..e58f89ec84 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index aa88fb502d..4e4070ed6f 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index f9f40ed3a0..4de0f35d79 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index aa2bc5d814..ec9a7b856c 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 389c8a4290..eb4369f07d 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,7 +18,7 @@

        Change History

        -

        Snapshot Build @qualified.bundle.version@ (@build.date@)

        +

        Release 0.8.13 (2025/04/02)

        New Features

          diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index 1c765c2019..8c8fcdf131 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index 67ea67ece9..e7f863910e 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index 04e62ffcae..0941470de2 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index e789d4f722..4c1b1a19ca 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index 1f657ce4c2..e8dd3af499 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index aa0e666363..705e78007a 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.13-SNAPSHOT + 0.8.13 ../org.jacoco.build diff --git a/pom.xml b/pom.xml index dc71687067..eafafe5514 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.13-SNAPSHOT + 0.8.13 pom From 23f698a35c7b7f85a6663acfb5da9b2b48106f42 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Tue, 1 Apr 2025 23:35:07 +0200 Subject: [PATCH 203/255] Prepare for next development iteration --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 33 insertions(+), 31 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index 0f8d9a06db..7d55c48a84 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index fa660549d9..61940a50a3 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index 0f0da04b2d..0df00081a1 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index 5cd18fa386..b7a42e0a0b 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index 8de9b8e89e..ed0040a0b4 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index f7902c5284..3e4844a0ee 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index 7d70fb756d..dcde39c139 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index 8e3dec25b1..88d87298b5 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index 6c6250c85b..1ad7cb4f90 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 0413ac4f1e..a3fec9a9dd 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index bdba3be214..d6b2ebb5cf 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index 6ecb2355ca..fb031f26be 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index e278afda7b..019eda0378 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index ed0c115355..313c9f5a54 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index d0521ec58c..1917fd753a 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index dd00a524c3..44f4e83cea 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index a1897ec9e9..f451de7ffd 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 764971363e..38618add59 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index 10f7f26a4c..3f0ba85e56 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 0e8a13a063..609325879e 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index e58f89ec84..8667081dd8 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 4e4070ed6f..79beb591f3 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index 4de0f35d79..75e00a37f0 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index ec9a7b856c..e9d0b72edd 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index eb4369f07d..ece5fd4585 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,6 +18,8 @@

          Change History

          +

          Snapshot Build @qualified.bundle.version@ (@build.date@)

          +

          Release 0.8.13 (2025/04/02)

          New Features

          diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index 8c8fcdf131..9b7f013ae3 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index e7f863910e..826f2275da 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index 0941470de2..93116051b9 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index 4c1b1a19ca..36f16a66e7 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index e8dd3af499..908fd630e3 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index 705e78007a..dc3666b932 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.13 + 0.8.14-SNAPSHOT ../org.jacoco.build diff --git a/pom.xml b/pom.xml index eafafe5514..eb9d68c508 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.13 + 0.8.14-SNAPSHOT pom From 5745d5cdcfed57ade4a41fe4b6c1e1d28c3417ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 20:34:43 +0200 Subject: [PATCH 204/255] Upgrade sonar-maven-plugin to 5.1.0.4751 (#1864) Bump org.sonarsource.scanner.maven:sonar-maven-plugin Bumps [org.sonarsource.scanner.maven:sonar-maven-plugin](https://github.com/SonarSource/sonar-scanner-maven) from 5.0.0.4389 to 5.1.0.4751. - [Release notes](https://github.com/SonarSource/sonar-scanner-maven/releases) - [Commits](https://github.com/SonarSource/sonar-scanner-maven/compare/5.0.0.4389...5.1.0.4751) --- updated-dependencies: - dependency-name: org.sonarsource.scanner.maven:sonar-maven-plugin dependency-version: 5.1.0.4751 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 a3fec9a9dd..ccf4feb0e0 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -455,7 +455,7 @@ org.sonarsource.scanner.maven sonar-maven-plugin - 5.0.0.4389 + 5.1.0.4751 From 32f4fc0d762498063f989d8cb73db0a37850753a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 3 Apr 2025 14:10:39 +0200 Subject: [PATCH 205/255] Fix KotlinDefaultArgumentsFilter for case when argument number 33 or higher has default value (#1655) --- .../targets/KotlinDefaultArgumentsTarget.kt | 4 +- .../KotlinDefaultArgumentsFilterTest.java | 38 +++++++++++++++++-- .../filter/KotlinDefaultArgumentsFilter.java | 7 ++-- org.jacoco.doc/docroot/doc/changes.html | 7 ++++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt index 75b490600f..6001f0c048 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt @@ -68,7 +68,7 @@ object KotlinDefaultArgumentsTarget { p30: String, // assertEmpty() p31: String, // assertEmpty() p32: String = "", // assertFullyCovered() - p33: String, // assertEmpty() + p33: String = "", // assertFullyCovered() ) // assertFullyCovered() @JvmStatic @@ -93,7 +93,7 @@ object KotlinDefaultArgumentsTarget { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", - "31", p33 = "" + "31", ) } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java index cac3272981..72ddb054fe 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java @@ -217,7 +217,7 @@ public void should_filter_methods_with_parameters_that_consume_two_slots() { * ... * p31: Int, * p32: Int = 42, - * p33: Int, + * p33: Int = 42, * ) *
    * @@ -242,11 +242,25 @@ public void should_filter_methods_with_more_than_32_parameters() { m.visitInsn(Opcodes.IAND); final Label label = new Label(); m.visitJumpInsn(Opcodes.IFEQ, label); + final Range range1 = new Range(m.instructions.getLast(), + m.instructions.getLast()); // default argument m.visitLdcInsn(Integer.valueOf(42)); m.visitVarInsn(Opcodes.ISTORE, 32); m.visitLabel(label); + m.visitVarInsn(Opcodes.ILOAD, 35); + m.visitInsn(Opcodes.ICONST_1); + m.visitInsn(Opcodes.IAND); + final Label label2 = new Label(); + m.visitJumpInsn(Opcodes.IFEQ, label2); + final Range range2 = new Range(m.instructions.getLast(), + m.instructions.getLast()); + // default argument + m.visitLdcInsn(Integer.valueOf(42)); + m.visitVarInsn(Opcodes.ISTORE, 33); + m.visitLabel(label2); + m.visitVarInsn(Opcodes.ALOAD, 0); for (int i = 1; i <= 33; i++) { m.visitVarInsn(Opcodes.ILOAD, i); @@ -257,15 +271,17 @@ public void should_filter_methods_with_more_than_32_parameters() { filter.filter(m, context, output); - assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + assertIgnored(range1, range2); } /** *
     	 * class C(
     	 *   p1: Int = 42,
    +	 *   p2: Int,
     	 *   ...
    -	 *   p225: Int,
    +	 *   p224: Int,
    +	 *   p225: Int = 42,
     	 * )
     	 * 
    * @@ -301,11 +317,25 @@ public void should_filter_methods_with_more_than_224_parameters() { m.visitInsn(Opcodes.IAND); final Label label = new Label(); m.visitJumpInsn(Opcodes.IFEQ, label); + final Range range1 = new Range(m.instructions.getLast(), + m.instructions.getLast()); // default argument m.visitLdcInsn(Integer.valueOf(42)); m.visitVarInsn(Opcodes.ISTORE, 1); m.visitLabel(label); + m.visitVarInsn(Opcodes.ILOAD, 233); + m.visitInsn(Opcodes.ICONST_1); + m.visitInsn(Opcodes.IAND); + final Label label2 = new Label(); + m.visitJumpInsn(Opcodes.IFEQ, label2); + final Range range2 = new Range(m.instructions.getLast(), + m.instructions.getLast()); + // default argument + m.visitLdcInsn(Integer.valueOf(42)); + m.visitVarInsn(Opcodes.ISTORE, 225); + m.visitLabel(label2); + m.visitVarInsn(Opcodes.ALOAD, 0); for (int i = 1; i <= 225; i++) { m.visitVarInsn(Opcodes.ILOAD, i); @@ -316,7 +346,7 @@ public void should_filter_methods_with_more_than_224_parameters() { filter.filter(m, context, output); - assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + assertIgnored(range1, range2); } @Test 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 e3b2a54688..1af4c04daa 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 @@ -12,8 +12,7 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -109,13 +108,13 @@ public void match(final MethodNode methodNode, cursor = skipNonOpcodes(methodNode.instructions.getFirst()); } - final Set ignore = new HashSet(); + final ArrayList ignore = new ArrayList(); final int maskVar = maskVar(methodNode.desc, constructor); while (true) { if (cursor.getOpcode() != Opcodes.ILOAD) { break; } - if (((VarInsnNode) cursor).var != maskVar) { + if (((VarInsnNode) cursor).var < maskVar) { break; } next(); diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index ece5fd4585..42d8256d37 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -20,6 +20,13 @@

    Change History

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    +

    New Features

    +
      +
    • Branches added by the Kotlin compiler for default argument number 33 or higher + are filtered out during generation of report + (GitHub #1655).
    • +
    +

    Release 0.8.13 (2025/04/02)

    New Features

    From e70580baa9f0d4ca2882659d134a2a97f80a267a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 9 Apr 2025 21:24:53 +0200 Subject: [PATCH 206/255] Use Ubuntu 24.04 (#1876) --- .azure-pipelines/azure-pipelines.yml | 2 +- .github/workflows/ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index 7ed12a5f88..55e581bb66 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -54,7 +54,7 @@ jobs: JDK 25: JDK_VERSION: 25 pool: - vmImage: 'ubuntu-20.04' + vmImage: 'ubuntu-24.04' steps: - bash: | set -e diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3c8ef4c7b..b3bd8186a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - jdk: 21 ecj: true name: JDK ${{ matrix.jdk }}${{ matrix.ecj && ' with ECJ' || ''}} - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 From 86f1b7a8ede706009a92bffd0172faa213c008f2 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 10 Apr 2025 21:10:05 +0200 Subject: [PATCH 207/255] Upgrade ECJ to 3.41.0 (#1642) --- .azure-pipelines/azure-pipelines.yml | 3 +++ org.jacoco.build/pom.xml | 2 +- .../core/test/validation/java21/RecordPatternsTest.java | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index 55e581bb66..7193d8a017 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -49,6 +49,9 @@ jobs: JDK_VERSION: 22 JDK 23: JDK_VERSION: 23 + JDK 23 with ECJ: + JDK_VERSION: 23 + ECJ: true JDK 24: JDK_VERSION: 24 JDK 25: diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index ccf4feb0e0..ecc6a28596 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -982,7 +982,7 @@ org.eclipse.jdt ecj - 3.37.0 + 3.41.0 org.codehaus.plexus diff --git a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java index a6d180b1de..f908f4cbd7 100644 --- a/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java +++ b/org.jacoco.core.test.validation.java21/src/org/jacoco/core/test/validation/java21/RecordPatternsTest.java @@ -27,7 +27,7 @@ public RecordPatternsTest() { } public void assertInstanceof(final Line line) { - if (JavaVersion.current().isBefore("23")) { + if (JavaVersion.current().isBefore("23") || !isJDKCompiler) { assertFullyCovered(line, 0, 2); } else { // TODO https://bugs.openjdk.org/browse/JDK-8303374 @@ -37,7 +37,9 @@ public void assertInstanceof(final Line line) { public void assertSwitchStatementLastCase(final Line line) { if (!isJDKCompiler) { + // TODO unfortunately // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773 + // did not fixed this issue assertPartlyCovered(line); } else if (JavaVersion.current().isBefore("23")) { assertFullyCovered(line); From f823d4343ee9039e6f6b40e1cd0c536808a712cb Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Fri, 11 Apr 2025 14:43:14 +0200 Subject: [PATCH 208/255] `IFilterOutput.replaceBranches` should allow the use of individual branches of instructions (#1813) --- .../targets/ControlStructuresTarget.java | 19 ++ .../java7/targets/StringSwitchTarget.java | 18 ++ .../targets/KotlinControlStructuresTarget.kt | 13 ++ .../kotlin/targets/KotlinWhenStringTarget.kt | 19 +- .../internal/analysis/InstructionTest.java | 55 +++++- .../internal/analysis/MethodAnalyzerTest.java | 171 +++++++++++++---- .../MethodCoverageCalculatorTest.java | 21 ++- .../filter/ExhaustiveSwitchFilterTest.java | 56 +++--- .../analysis/filter/FilterTestBase.java | 86 +++++++-- .../analysis/filter/FinallyFilterTest.java | 4 +- .../KotlinSafeCallOperatorFilterTest.java | 44 +++-- .../analysis/filter/KotlinWhenFilterTest.java | 27 +-- .../filter/KotlinWhenStringFilterTest.java | 37 ++-- .../analysis/filter/ReplacementsTest.java | 131 +++++++++++++ .../filter/StringSwitchFilterTest.java | 94 ++++----- .../core/internal/analysis/Instruction.java | 42 +++-- .../analysis/MethodCoverageCalculator.java | 28 ++- .../filter/ExhaustiveSwitchFilter.java | 13 +- .../analysis/filter/IFilterOutput.java | 9 +- .../filter/KotlinSafeCallOperatorFilter.java | 16 +- .../analysis/filter/KotlinWhenFilter.java | 25 +-- .../filter/KotlinWhenStringFilter.java | 15 +- .../analysis/filter/Replacements.java | 178 ++++++++++++++++++ .../analysis/filter/StringSwitchFilter.java | 14 +- org.jacoco.doc/docroot/doc/changes.html | 10 + 25 files changed, 867 insertions(+), 278 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ReplacementsTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java index 4fe11d458f..63727ab680 100644 --- a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java +++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java @@ -43,6 +43,9 @@ public static void main(String[] args) { lookupSwitchWithHit(); continuedLookupSwitchWithHit(); lookupSwitchWithoutHit(); + switchImplicitDefaultNotExecuted(0); + switchImplicitDefaultNotExecuted(1); + switchImplicitDefaultNotExecuted(2); breakStatement(); continueStatement(); conditionalReturn(); @@ -250,6 +253,22 @@ private static void lookupSwitchWithoutHit() { } + private static void switchImplicitDefaultNotExecuted(final int i) { + + switch (i) { // assertFullyCovered(1, 3) + case 0: + nop(); // assertFullyCovered() + break; + case 1: + nop(); // assertFullyCovered() + break; + case 2: + nop(); // assertFullyCovered() + break; + } + + } + private static void breakStatement() { while (true) { diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java index 2c467320d9..575f370784 100644 --- a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java +++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java @@ -53,6 +53,20 @@ private static void notCovered(Object s) { } } + private static void implicitDefaultNotExecuted(Object s) { + switch (String.valueOf(s)) { // assertFullyCovered(1, 3) + case "a": + nop("case a"); // assertFullyCovered() + break; + case "b": + nop("case b"); // assertFullyCovered() + break; + case "c": + nop("case c"); // assertFullyCovered() + break; + } + } + private static void handwritten(String s) { int c = -1; switch (s.hashCode()) { // assertFullyCovered(2, 1) @@ -119,6 +133,10 @@ public static void main(String[] args) { covered("b"); covered("\0a"); + implicitDefaultNotExecuted("a"); + implicitDefaultNotExecuted("b"); + implicitDefaultNotExecuted("c"); + handwritten("a"); default_is_first(""); diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt index e4200b2cb7..4574c4d999 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinControlStructuresTarget.kt @@ -112,6 +112,16 @@ object KotlinControlStructuresTarget { } + private fun whenImplicitElseNotExecuted(i: Int) { + + when (i) { // assertFullyCovered(1, 3) + 0 -> nop() // assertFullyCovered() + 1 -> nop() // assertFullyCovered() + 2 -> nop() // assertFullyCovered() + } + + } + private fun breakStatement() { while (true) { @@ -156,6 +166,9 @@ object KotlinControlStructuresTarget { missedForEachBlock() executedForEachBlock() whenExpression() + whenImplicitElseNotExecuted(0) + whenImplicitElseNotExecuted(1) + whenImplicitElseNotExecuted(2) breakStatement() continueStatement() implicitReturn() 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 index a8fa8152ee..2ff0c227c3 100644 --- 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 @@ -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 `String`. + * Test target with `when` expressions and statements with subject of type `String`. */ object KotlinWhenStringTarget { @@ -44,6 +46,17 @@ object KotlinWhenStringTarget { else -> "else" // assertFullyCovered() } // assertFullyCovered() + /** + * @see KotlinControlStructuresTarget.whenImplicitElseNotExecuted + */ + private fun implicitElseNotExecuted(s: String) { + when (s) { // assertFullyCovered(1, 3) + "a" -> nop("case a") // assertFullyCovered() + "b" -> nop("case b") // assertFullyCovered() + "c" -> nop("case c") // assertFullyCovered() + } // assertEmpty() + } // assertFullyCovered() + /** * Unlike [whenString] * in this example first case is the only case with biggest hashCode value. @@ -79,6 +92,10 @@ object KotlinWhenStringTarget { whenStringNullableCase(null) whenStringNullableCase("") + implicitElseNotExecuted("a") + implicitElseNotExecuted("b") + implicitElseNotExecuted("c") + whenStringBiggestHashCodeFirst("") whenStringBiggestHashCodeFirst("a") whenStringBiggestHashCodeFirst("b") diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java index 7cc548378a..0909f6d04c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java @@ -14,10 +14,14 @@ import static org.junit.Assert.assertEquals; -import java.util.Arrays; +import java.util.HashMap; +import org.jacoco.core.internal.analysis.filter.Replacements; import org.junit.Before; import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.InsnNode; /** * Unit tests for {@link Instruction}. @@ -161,14 +165,59 @@ public void merge_should_calculate_superset_of_covered_branches() { @Test public void replaceBranches_should_calculate_coverage_on_new_branches() { + final InsnNode n1 = new InsnNode(Opcodes.NOP); + final InsnNode n2 = new InsnNode(Opcodes.NOP); + final InsnNode n3 = new InsnNode(Opcodes.NOP); + final HashMap map = new HashMap(); + final Instruction.Mapper mapper = new Instruction.Mapper() { + public Instruction apply(final AbstractInsnNode node) { + return map.get(node); + } + }; + Instruction i1 = new Instruction(1); + map.put(n1, i1); Instruction i2 = new Instruction(2); + map.put(n2, i2); Instruction i3 = new Instruction(3); - i3.addBranch(true, 0); + map.put(n3, i3); + i3.addBranch(false, 0); + i3.addBranch(true, 1); + + Replacements replacements = new Replacements(); + replacements.add(n1, n1, 0); + replacements.add(n2, n2, 0); + replacements.add(n3, n3, 0); + instruction = instruction.replaceBranches(replacements, mapper); + assertEquals(CounterImpl.getInstance(3, 0), + instruction.getBranchCounter()); - instruction = instruction.replaceBranches(Arrays.asList(i1, i2, i3)); + replacements = new Replacements(); + replacements.add(n1, n1, 0); + replacements.add(n2, n2, 0); + replacements.add(n3, n3, 1); + instruction = instruction.replaceBranches(replacements, mapper); + assertEquals(CounterImpl.getInstance(2, 1), + instruction.getBranchCounter()); + replacements = new Replacements(); + replacements.add(n3, n3, 1); + replacements.add(n2, n3, 1); + replacements.add(n1, n1, 0); + instruction = instruction.replaceBranches(replacements, mapper); + assertEquals(CounterImpl.getInstance(1, 2), + instruction.getBranchCounter()); + + replacements = new Replacements(); + replacements.add(n1, n1, 0); + replacements.add(n2, n2, 0); + // branch should be considered executed + // when at least one of replacements branches was executed + replacements.add(n3, n3, 1); + replacements.add(n3, n3, 0); + instruction = instruction.replaceBranches(replacements, mapper); assertEquals(CounterImpl.getInstance(2, 1), instruction.getBranchCounter()); } + } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java index 6124a46c20..f4fb67e984 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java @@ -15,8 +15,6 @@ import static org.junit.Assert.assertEquals; import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; import org.jacoco.core.analysis.ILine; import org.jacoco.core.analysis.IMethodCoverage; @@ -26,6 +24,7 @@ import org.jacoco.core.internal.analysis.filter.IFilter; import org.jacoco.core.internal.analysis.filter.IFilterContext; import org.jacoco.core.internal.analysis.filter.IFilterOutput; +import org.jacoco.core.internal.analysis.filter.Replacements; import org.jacoco.core.internal.flow.IProbeIdGenerator; import org.jacoco.core.internal.flow.LabelFlowAnalyzer; import org.jacoco.core.internal.flow.MethodProbesAdapter; @@ -34,6 +33,7 @@ import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.util.CheckMethodAdapter; @@ -514,7 +514,137 @@ public void jump_to_first_instruction_should_show_full_branch_coverage_when_prob assertLine(1002, 0, 1, 0, 0); } - // === Scenario: table switch with and without replace filtering === + // === Scenario: replace filtering of Kotlin safe call followed by elvis === + + /** + *
    +	 * data class B(val c: String)
    +	 * fun safeCallElvis(b: B?): String =
    +	 *     b?.c ?: ""
    +	 * 
    + */ + private void createKotlinSafeCallElvis() { + final Label l0 = new Label(); + method.visitLabel(l0); + method.visitLineNumber(1001, l0); + final Label l1 = new Label(); + final Label l2 = new Label(); + method.visitVarInsn(Opcodes.ALOAD, 0); + method.visitInsn(Opcodes.DUP); + // probe[0] when jump to l1 + method.visitJumpInsn(Opcodes.IFNULL, l1); + method.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC", + "()Ljava/lang/String;", false); + method.visitInsn(Opcodes.DUP); + // probe[1] when jump to l2 + method.visitJumpInsn(Opcodes.IFNONNULL, l2); + // probe[2] is unreachable because `b.c` can not be null + method.visitLabel(l1); + method.visitInsn(Opcodes.POP); + method.visitLdcInsn(""); + // probe[3] + method.visitLabel(l2); + // probe[4] + method.visitInsn(Opcodes.ARETURN); + } + + @Test + public void kotlin_safe_call_elvis_should_create_4_probes() { + createKotlinSafeCallElvis(); + runMethodAnalzer(); + assertEquals(5, nextProbeId); + } + + private static final IFilter KOTLIN_SAFE_CALL_ELVIS_FILTER = new IFilter() { + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + final AbstractInsnNode ifNullInstruction = methodNode.instructions + .get(4); + assertEquals(Opcodes.IFNULL, ifNullInstruction.getOpcode()); + final AbstractInsnNode ifNonNullInstruction = methodNode.instructions + .get(7); + assertEquals(Opcodes.IFNONNULL, ifNonNullInstruction.getOpcode()); + final AbstractInsnNode nullTarget = ((JumpInsnNode) ifNullInstruction).label; + final AbstractInsnNode nonNullTarget = ((JumpInsnNode) ifNonNullInstruction).label; + final Replacements replacements = new Replacements(); + replacements.add(nullTarget, ifNonNullInstruction, 0); + replacements.add(nullTarget, ifNullInstruction, 1); + replacements.add(nonNullTarget, ifNonNullInstruction, 1); + output.replaceBranches(ifNonNullInstruction, replacements); + } + }; + + /** + * Execution of + * + *
    +	 * safeCallElvis(B(""))
    +	 * 
    + */ + @Test + public void kotlin_safe_call_elvis_with_filter_should_show_partial_branch_coverage_when_only_non_null_case_covered() { + createKotlinSafeCallElvis(); + probes[1] = true; + probes[4] = true; + runMethodAnalzer(KOTLIN_SAFE_CALL_ELVIS_FILTER); + + assertLine(1001, 2, 7, 2, 2); + } + + /** + * Execution of + * + *
    +	 * safeCallElvis(null)
    +	 * 
    + */ + @Test + public void kotlin_safe_call_elvis_with_filter_should_show_partial_branch_coverage_when_only_null_case_covered() { + createKotlinSafeCallElvis(); + probes[0] = true; + probes[3] = true; + runMethodAnalzer(KOTLIN_SAFE_CALL_ELVIS_FILTER); + + assertLine(1001, 3, 6, 2, 2); + } + + /** + * Execution of + * + *
    +	 * safeCallElvis(null)
    +	 * safeCallElvis(B(""))
    +	 * 
    + */ + @Test + public void kotlin_safe_call_elvis_with_filter_should_show_full_branch_coverage_when_both_cases_covered() { + createKotlinSafeCallElvis(); + // non-null case + probes[1] = true; + probes[4] = true; + // null case + probes[0] = true; + probes[3] = true; + runMethodAnalzer(KOTLIN_SAFE_CALL_ELVIS_FILTER); + + assertLine(1001, 0, 9, 0, 4); + } + + @Test + public void kotlin_safe_call_elvis_without_filter() { + createKotlinSafeCallElvis(); + // non-null case + probes[1] = true; + probes[4] = true; + // null case + probes[0] = true; + probes[3] = true; + runMethodAnalzer(); + + assertLine(1001, 0, 9, 1, 3); + } + + // === Scenario: table switch === private void createTableSwitch() { final Label l0 = new Label(); @@ -559,41 +689,6 @@ public void table_switch_should_create_4_probes() { assertEquals(4, nextProbeId); } - private static final IFilter SWITCH_FILTER = new IFilter() { - public void filter(final MethodNode methodNode, - final IFilterContext context, final IFilterOutput output) { - final AbstractInsnNode i = methodNode.instructions.get(3); - assertEquals(Opcodes.TABLESWITCH, i.getOpcode()); - final AbstractInsnNode t1 = methodNode.instructions.get(6); - assertEquals(Opcodes.BIPUSH, t1.getOpcode()); - final AbstractInsnNode t2 = methodNode.instructions.get(13); - assertEquals(Opcodes.BIPUSH, t2.getOpcode()); - - final Set newTargets = new HashSet(); - newTargets.add(t1); - newTargets.add(t2); - output.replaceBranches(i, newTargets); - } - }; - - @Test - public void table_switch_with_filter_should_show_2_branches_when_original_replaced() { - createTableSwitch(); - runMethodAnalzer(SWITCH_FILTER); - - assertLine(1001, 2, 0, 2, 0); - } - - @Test - public void table_switch_with_filter_should_show_full_branch_coverage_when_new_targets_covered() { - createTableSwitch(); - probes[0] = true; - probes[1] = true; - runMethodAnalzer(SWITCH_FILTER); - - assertLine(1001, 0, 2, 0, 2); - } - @Test public void table_switch_should_show_missed_when_no_probes_are_executed() { createTableSwitch(); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java index b0f41b8388..8613091adc 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java @@ -14,12 +14,11 @@ import static org.junit.Assert.assertEquals; -import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import org.jacoco.core.analysis.ISourceNode; +import org.jacoco.core.internal.analysis.filter.Replacements; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Opcodes; @@ -173,17 +172,20 @@ public void should_merge_instructions_redundant() { @Test public void should_replace_branches() { InsnNode i1 = addInsn(1); - InsnNode i2 = addInsn(2, true); + InsnNode i2 = addInsn(2, false, true); InsnNode i3 = addInsn(2, true); InsnNode i4 = addInsn(2, false); MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); - c.replaceBranches(i1, - new HashSet(Arrays.asList(i2, i3, i4))); + Replacements replacements = new Replacements(); + replacements.add(i2, i2, 1); + replacements.add(i3, i3, 0); + replacements.add(i4, i4, 0); + c.replaceBranches(i1, replacements); c.calculate(coverage); assertLine(1, 0, 1, 1, 2); // branches coverage status replaced - assertLine(2, 1, 2, 0, 0); // still in place + assertLine(2, 1, 2, 1, 1); // still in place } @Test @@ -196,8 +198,11 @@ public void should_replace_branches_with_merged_instructions() { MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); c.merge(i4, i3); c.merge(i3, i2); - c.replaceBranches(i1, - new HashSet(Arrays.asList(i2, i3, i4))); + Replacements replacements = new Replacements(); + replacements.add(i2, i2, 0); + replacements.add(i3, i3, 0); + replacements.add(i4, i4, 0); + c.replaceBranches(i1, replacements); c.calculate(coverage); assertLine(1, 0, 1, 0, 3); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java index f9429192e5..d3d4e4c3d9 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java @@ -12,8 +12,7 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; import org.jacoco.core.internal.instr.InstrSupport; import org.junit.Test; @@ -29,15 +28,17 @@ public class ExhaustiveSwitchFilterTest extends FilterTestBase { private final IFilter filter = new ExhaustiveSwitchFilter(); + private final ArrayList replacements = new ArrayList(); + /** *
     	 *   enum E {
    -	 *     A, B, C
    +	 *     A, B, C, D
     	 *   }
     	 *
     	 *   int example(E e) {
     	 *     return switch (e) {
    -	 *       case A -> 1;
    +	 *       case A, D -> 1;
     	 *       case B -> 2;
     	 *       case C -> 3;
     	 *     };
    @@ -64,10 +65,12 @@ public void should_filter_when_default_branch_has_LineNumber_of_switch() {
     		final Label case1 = new Label();
     		final Label case2 = new Label();
     		final Label case3 = new Label();
    -		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3 },
    -				new Label[] { case1, case2, case3 });
    +		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3, 4 },
    +				new Label[] { case1, case2, case3, case1 });
     		final AbstractInsnNode switchNode = m.instructions.getLast();
    -		final Set newTargets = new HashSet();
    +		replacements.add(new Replacement(0, switchNode, 1));
    +		replacements.add(new Replacement(1, switchNode, 2));
    +		replacements.add(new Replacement(2, switchNode, 3));
     
     		m.visitLabel(dflt);
     		final Range range = new Range();
    @@ -83,16 +86,13 @@ public void should_filter_when_default_branch_has_LineNumber_of_switch() {
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.ICONST_1);
    -		newTargets.add(m.instructions.getLast());
     		m.visitJumpInsn(Opcodes.GOTO, end);
     
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.ICONST_2);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.ICONST_3);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(end);
     		m.visitInsn(Opcodes.IRETURN);
    @@ -100,18 +100,18 @@ public void should_filter_when_default_branch_has_LineNumber_of_switch() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(switchNode, newTargets);
    +		assertReplacedBranches(m, switchNode, replacements);
     	}
     
     	/**
     	 * 
     	 *   enum E {
    -	 *     A, B, C
    +	 *     A, B, C, D
     	 *   }
     	 *
     	 *   int example(E e) {
     	 *     return switch (e) {
    -	 *       case A -> 1;
    +	 *       case A, D -> 1;
     	 *       case B -> 2;
     	 *       case C -> 3;
     	 *     };
    @@ -138,10 +138,12 @@ public void should_filter_when_default_branch_has_no_LineNumber() {
     		final Label case1 = new Label();
     		final Label case2 = new Label();
     		final Label case3 = new Label();
    -		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3 },
    -				new Label[] { case1, case2, case3 });
    +		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3, 4 },
    +				new Label[] { case1, case2, case3, case1 });
     		final AbstractInsnNode switchNode = m.instructions.getLast();
    -		final Set newTargets = new HashSet();
    +		replacements.add(new Replacement(0, switchNode, 1));
    +		replacements.add(new Replacement(1, switchNode, 2));
    +		replacements.add(new Replacement(2, switchNode, 3));
     
     		m.visitLabel(dflt);
     		final Range range = new Range();
    @@ -156,16 +158,13 @@ public void should_filter_when_default_branch_has_no_LineNumber() {
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.ICONST_1);
    -		newTargets.add(m.instructions.getLast());
     		m.visitJumpInsn(Opcodes.GOTO, end);
     
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.ICONST_2);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.ICONST_3);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(end);
     		m.visitInsn(Opcodes.IRETURN);
    @@ -173,18 +172,18 @@ public void should_filter_when_default_branch_has_no_LineNumber() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(switchNode, newTargets);
    +		assertReplacedBranches(m, switchNode, replacements);
     	}
     
     	/**
     	 * 
     	 *   enum E {
    -	 *     A, B, C
    +	 *     A, B, C, D
     	 *   }
     	 *
     	 *   int example(E e) {
     	 *     return switch (e) {
    -	 *       case A -> 1;
    +	 *       case A, D -> 1;
     	 *       case B -> 2;
     	 *       case C -> 3;
     	 *     };
    @@ -211,10 +210,12 @@ public void should_filter_when_default_branch_throws_Java_21_MatchException() {
     		final Label case1 = new Label();
     		final Label case2 = new Label();
     		final Label case3 = new Label();
    -		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3 },
    -				new Label[] { case1, case2, case3 });
    +		m.visitLookupSwitchInsn(dflt, new int[] { 1, 2, 3, 4 },
    +				new Label[] { case1, case2, case3, case1 });
     		final AbstractInsnNode switchNode = m.instructions.getLast();
    -		final Set newTargets = new HashSet();
    +		replacements.add(new Replacement(0, switchNode, 1));
    +		replacements.add(new Replacement(1, switchNode, 2));
    +		replacements.add(new Replacement(2, switchNode, 3));
     
     		m.visitLabel(dflt);
     		final Range range = new Range();
    @@ -230,16 +231,13 @@ public void should_filter_when_default_branch_throws_Java_21_MatchException() {
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.ICONST_1);
    -		newTargets.add(m.instructions.getLast());
     		m.visitJumpInsn(Opcodes.GOTO, end);
     
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.ICONST_2);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.ICONST_3);
    -		newTargets.add(m.instructions.getLast());
     
     		m.visitLabel(end);
     		m.visitInsn(Opcodes.IRETURN);
    @@ -247,7 +245,7 @@ public void should_filter_when_default_branch_throws_Java_21_MatchException() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(switchNode, newTargets);
    +		assertReplacedBranches(m, switchNode, replacements);
     	}
     
     	/**
    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 b9210dd004..7e27582131 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
    @@ -18,11 +18,12 @@
     import static org.junit.Assert.fail;
     
     import java.util.ArrayList;
    +import java.util.Collection;
     import java.util.Collections;
    +import java.util.Comparator;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
    -import java.util.Set;
     
     import org.objectweb.asm.tree.AbstractInsnNode;
     import org.objectweb.asm.tree.MethodNode;
    @@ -36,7 +37,7 @@ public abstract class FilterTestBase {
     
     	private final List ignoredRanges = new ArrayList();
     
    -	private final Map> replacedBranches = new HashMap>();
    +	private final HashMap>> actualReplacements = new HashMap>>();
     
     	protected final IFilterOutput output = new IFilterOutput() {
     		public void ignore(final AbstractInsnNode fromInclusive,
    @@ -52,9 +53,9 @@ public void merge(final AbstractInsnNode i1,
     			fail();
     		}
     
    -		public void replaceBranches(final AbstractInsnNode source,
    -				final Set newTargets) {
    -			replacedBranches.put(source, newTargets);
    +		public void replaceBranches(AbstractInsnNode source,
    +				Replacements replacements) {
    +			actualReplacements.put(source, replacements.values());
     		}
     	};
     
    @@ -68,17 +69,78 @@ final void assertMethodIgnored(final MethodNode m) {
     	}
     
     	final void assertNoReplacedBranches() {
    -		assertTrue(replacedBranches.isEmpty());
    +		assertTrue(actualReplacements.isEmpty());
     	}
     
    -	final void assertReplacedBranches(final AbstractInsnNode source,
    -			final Set newTargets) {
    -		assertReplacedBranches(Collections.singletonMap(source, newTargets));
    +	final void assertReplacedBranches(final MethodNode methodNode,
    +			final AbstractInsnNode source,
    +			final List expectedReplacements) {
    +		assertReplacedBranches(methodNode,
    +				Collections.singletonMap(source, expectedReplacements));
     	}
     
    -	final void assertReplacedBranches(
    -			final Map> expected) {
    -		assertEquals(expected, replacedBranches);
    +	final void assertReplacedBranches(final MethodNode methodNode,
    +			final Map> expectedReplacements) {
    +		assertEquals(expectedReplacements.size(), actualReplacements.size());
    +		for (final Map.Entry> entry : expectedReplacements
    +				.entrySet()) {
    +			final AbstractInsnNode node = entry.getKey();
    +			final List replacements = entry.getValue();
    +			assertReplacements(methodNode, node, replacements);
    +		}
    +	}
    +
    +	private void assertReplacements(final MethodNode methodNode,
    +			final AbstractInsnNode source,
    +			final List expectedReplacements) {
    +
    +		Collections.sort(expectedReplacements, new Comparator() {
    +			public int compare(final Replacement r1, final Replacement r2) {
    +				if (r1.newBranch == r2.newBranch) {
    +					return r1.branch - r2.branch;
    +				}
    +				return r1.newBranch - r2.newBranch;
    +			}
    +		});
    +
    +		final StringBuilder expectedStringBuilder = new StringBuilder();
    +		for (final Replacement replacement : expectedReplacements) {
    +			expectedStringBuilder.append(replacement.newBranch)
    +					.append(" if branch ").append(replacement.branch)
    +					.append(" of instruction ").append(methodNode.instructions
    +							.indexOf(replacement.instruction))
    +					.append("\n");
    +		}
    +
    +		final StringBuilder actualStringBuilder = new StringBuilder();
    +		int newBranch = 0;
    +		for (final Collection pairs : actualReplacements
    +				.get(source)) {
    +			for (Replacements.InstructionBranch pair : pairs) {
    +				actualStringBuilder.append(newBranch).append(" if branch ")
    +						.append(pair.branch).append(" of instruction ")
    +						.append(methodNode.instructions
    +								.indexOf(pair.instruction))
    +						.append("\n");
    +			}
    +			newBranch++;
    +		}
    +
    +		assertEquals(expectedStringBuilder.toString(),
    +				actualStringBuilder.toString());
    +	}
    +
    +	static class Replacement {
    +		final int newBranch;
    +		final AbstractInsnNode instruction;
    +		final int branch;
    +
    +		Replacement(final int newBranch, final AbstractInsnNode instruction,
    +				final int branch) {
    +			this.newBranch = newBranch;
    +			this.instruction = instruction;
    +			this.branch = branch;
    +		}
     	}
     
     	static class Range {
    diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
    index 876ff161fa..76ccafcd21 100644
    --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
    +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
    @@ -422,8 +422,8 @@ public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
     		}
     	}
     
    -	public void replaceBranches(final AbstractInsnNode source,
    -			final Set newTargets) {
    +	public void replaceBranches(AbstractInsnNode source,
    +			Replacements replacements) {
     		fail();
     	}
     
    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
    index 3ec105136b..2c6455fc8d 100644
    --- 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
    @@ -12,9 +12,9 @@
      *******************************************************************************/
     package org.jacoco.core.internal.analysis.filter;
     
    +import java.util.Arrays;
     import java.util.HashMap;
    -import java.util.HashSet;
    -import java.util.Set;
    +import java.util.List;
     
     import org.jacoco.core.internal.instr.InstrSupport;
     import org.junit.Test;
    @@ -52,32 +52,34 @@ public void should_filter_optimized_safe_call_chain() {
     
     		m.visitInsn(Opcodes.DUP);
     		m.visitJumpInsn(Opcodes.IFNULL, label1);
    -		final AbstractInsnNode i1 = m.instructions.getLast();
    +		final AbstractInsnNode ifNullInstruction1 = 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();
    +		final AbstractInsnNode ifNullInstruction2 = 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());
    +		final AbstractInsnNode popInstruction = 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);
    +		final HashMap> replacements = new HashMap>();
    +		replacements.put(ifNullInstruction1, Arrays.asList( //
    +				new Replacement(0, ifNullInstruction2, 0),
    +				new Replacement(1, popInstruction, 0)));
    +		replacements.put(ifNullInstruction2, Arrays.asList( //
    +				new Replacement(0, ifNullInstruction2, 0),
    +				new Replacement(1, popInstruction, 0)));
    +		assertReplacedBranches(m, replacements);
     	}
     
     	/**
    @@ -101,17 +103,15 @@ public void should_filter_unoptimized_safe_call_chain() {
     		final Label label2 = new Label();
     
     		m.visitJumpInsn(Opcodes.IFNULL, label1);
    -		final AbstractInsnNode i1 = m.instructions.getLast();
    +		final AbstractInsnNode ifNullInstruction1 = m.instructions.getLast();
     		m.visitVarInsn(Opcodes.ALOAD, 0);
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "A", "getB", "()LB;", false);
     
     		m.visitVarInsn(Opcodes.ASTORE, 1);
     		m.visitVarInsn(Opcodes.ALOAD, 1);
     		m.visitJumpInsn(Opcodes.IFNULL, label1);
    -		final AbstractInsnNode i2 = m.instructions.getLast();
    +		final AbstractInsnNode ifNullInstruction2 = m.instructions.getLast();
     		m.visitVarInsn(Opcodes.ALOAD, 1);
    -		final HashSet r = new HashSet();
    -		r.add(m.instructions.getLast());
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC",
     				"()Ljava/lang/String;", false);
     
    @@ -119,16 +119,20 @@ public void should_filter_unoptimized_safe_call_chain() {
     
     		m.visitLabel(label1);
     		m.visitInsn(Opcodes.ACONST_NULL);
    -		r.add(m.instructions.getLast());
    +		final AbstractInsnNode aconstNullInstruction = m.instructions.getLast();
     		m.visitLabel(label2);
     
     		filter.filter(m, context, output);
     
     		assertIgnored();
    -		final HashMap> expected = new HashMap>();
    -		expected.put(i1, r);
    -		expected.put(i2, r);
    -		assertReplacedBranches(expected);
    +		final HashMap> replacements = new HashMap>();
    +		replacements.put(ifNullInstruction1, Arrays.asList( //
    +				new Replacement(0, ifNullInstruction2, 0),
    +				new Replacement(1, aconstNullInstruction, 0)));
    +		replacements.put(ifNullInstruction2, Arrays.asList( //
    +				new Replacement(0, ifNullInstruction2, 0),
    +				new Replacement(1, aconstNullInstruction, 0)));
    +		assertReplacedBranches(m, replacements);
     	}
     
     }
    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 42644ff522..1d87f1d28f 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
    @@ -12,8 +12,7 @@
      *******************************************************************************/
     package org.jacoco.core.internal.analysis.filter;
     
    -import java.util.HashSet;
    -import java.util.Set;
    +import java.util.ArrayList;
     
     import org.jacoco.core.internal.instr.InstrSupport;
     import org.junit.Test;
    @@ -32,6 +31,8 @@ public class KotlinWhenFilterTest extends FilterTestBase {
     	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     			"name", "()V", null, null);
     
    +	private final ArrayList replacements = new ArrayList();
    +
     	@Test
     	public void should_filter_implicit_else() {
     		final Label label = new Label();
    @@ -96,11 +97,10 @@ public void should_filter_implicit_default() {
     
     		m.visitTableSwitchInsn(0, 0, caseDefault, case1);
     		final AbstractInsnNode switchNode = m.instructions.getLast();
    -		final Set newTargets = new HashSet();
    +		replacements.add(new Replacement(0, switchNode, 1));
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.ICONST_1);
    -		newTargets.add(m.instructions.getLast());
     		m.visitJumpInsn(Opcodes.GOTO, after);
     
     		final Range range1 = new Range();
    @@ -118,7 +118,7 @@ public void should_filter_implicit_default() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range1);
    -		assertReplacedBranches(switchNode, newTargets);
    +		assertReplacedBranches(m, switchNode, replacements);
     	}
     
     	/**
    @@ -135,7 +135,6 @@ public void should_filter_implicit_default() {
     	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();
    @@ -162,23 +161,27 @@ public void should_filter_when_by_nullable_enum_with_null_case_and_without_else(
     		m.visitInsn(Opcodes.IALOAD);
     		m.visitLabel(l2);
     		range1.toInclusive = m.instructions.getLast();
    -		m.visitTableSwitchInsn(-1, 2, caseElse, caseNull, caseElse, caseA,
    -				caseB);
    +		m.visitTableSwitchInsn(-1, 2, //
    +				caseElse, // branch 0
    +				caseNull, // branch 1
    +				caseElse, // branch 0
    +				caseA, // branch 2
    +				caseB); // branch 3
     		final AbstractInsnNode switchNode = m.instructions.getLast();
    +		replacements.add(new Replacement(0, switchNode, 1));
    +		replacements.add(new Replacement(1, switchNode, 2));
    +		replacements.add(new Replacement(2, switchNode, 3));
     
     		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);
    @@ -196,7 +199,7 @@ public void should_filter_when_by_nullable_enum_with_null_case_and_without_else(
     		filter.filter(m, context, output);
     
     		assertIgnored(range1, range2);
    -		assertReplacedBranches(switchNode, newTargets);
    +		assertReplacedBranches(m, switchNode, replacements);
     	}
     
     	/**
    diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java
    index dbc5578833..0cd7fd9a41 100644
    --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java
    +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java
    @@ -12,8 +12,7 @@
      *******************************************************************************/
     package org.jacoco.core.internal.analysis.filter;
     
    -import java.util.HashSet;
    -import java.util.Set;
    +import java.util.ArrayList;
     
     import org.jacoco.core.internal.instr.InstrSupport;
     import org.junit.Test;
    @@ -29,10 +28,10 @@ public class KotlinWhenStringFilterTest extends FilterTestBase {
     
     	private final IFilter filter = new KotlinWhenStringFilter();
     
    +	private final ArrayList replacements = new ArrayList();
    +
     	@Test
     	public void should_filter() {
    -		final Set expectedNewTargets = new HashSet();
    -
     		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     				"name", "()V", null, null);
     
    @@ -55,6 +54,7 @@ public void should_filter() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
     				"()I", false);
     		m.visitTableSwitchInsn(97, 98, defaultCase, h1, h2);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		// case "a"
     		m.visitLabel(h1);
    @@ -66,6 +66,7 @@ public void should_filter() {
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, sameHash);
     		m.visitJumpInsn(Opcodes.GOTO, case1);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 0));
     
     		// case "\u0000a"
     		m.visitLabel(sameHash);
    @@ -74,7 +75,9 @@ public void should_filter() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, case2);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 0));
     
     		// case "b"
     		m.visitLabel(h2);
    @@ -83,26 +86,24 @@ public void should_filter() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, case3);
     		final AbstractInsnNode expectedToInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 0));
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(defaultCase);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		filter.filter(m, context, output);
     
    -		assertReplacedBranches(expectedFromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, expectedFromInclusive.getPrevious(),
    +				replacements);
     		assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
     	}
     
    @@ -119,8 +120,6 @@ public void should_filter() {
     	 */
     	@Test
     	public void should_filter_when_biggest_hashCode_first() {
    -		final Set expectedNewTargets = new HashSet();
    -
     		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     				"example", "(Ljava/lang/String;)V", null, null);
     
    @@ -136,6 +135,7 @@ public void should_filter_when_biggest_hashCode_first() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
     				"()I", false);
     		m.visitTableSwitchInsn(97, 98, defaultCase, h1, h2);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h1);
     		final AbstractInsnNode expectedFromInclusive = m.instructions.getLast();
    @@ -145,6 +145,7 @@ public void should_filter_when_biggest_hashCode_first() {
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, sameHash);
     		m.visitJumpInsn(Opcodes.GOTO, case2);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 0));
     
     		m.visitLabel(sameHash);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -152,7 +153,9 @@ public void should_filter_when_biggest_hashCode_first() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, case3);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 0));
     
     		m.visitLabel(h2);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -161,25 +164,23 @@ public void should_filter_when_biggest_hashCode_first() {
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
     		final AbstractInsnNode expectedToInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 1));
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 0));
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(defaultCase);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		filter.filter(m, context, output);
     
     		assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
    -		assertReplacedBranches(expectedFromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, expectedFromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	@Test
    diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ReplacementsTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ReplacementsTest.java
    new file mode 100644
    index 0000000000..6828771b37
    --- /dev/null
    +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ReplacementsTest.java
    @@ -0,0 +1,131 @@
    +/*******************************************************************************
    + * Copyright (c) 2009, 2025 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 static org.junit.Assert.assertFalse;
    +import static org.junit.Assert.assertTrue;
    +
    +import java.util.ArrayList;
    +import java.util.Arrays;
    +import java.util.Collection;
    +import java.util.Collections;
    +import java.util.Iterator;
    +
    +import org.junit.Assert;
    +import org.junit.Test;
    +import org.objectweb.asm.Opcodes;
    +import org.objectweb.asm.tree.InsnNode;
    +import org.objectweb.asm.tree.LabelNode;
    +import org.objectweb.asm.tree.LookupSwitchInsnNode;
    +import org.objectweb.asm.tree.TableSwitchInsnNode;
    +
    +/**
    + * Unit test for {@link Replacements}.
    + */
    +public class ReplacementsTest {
    +
    +	@Test
    +	public void should_accumulate() {
    +		final Replacements replacements = new Replacements();
    +		final InsnNode target1 = new InsnNode(Opcodes.NOP);
    +		final InsnNode target2 = new InsnNode(Opcodes.NOP);
    +		final InsnNode fromInstruction = new InsnNode(Opcodes.NOP);
    +
    +		replacements.add(target1, fromInstruction, 0);
    +		replacements.add(target2, fromInstruction, 1);
    +		ArrayList> expected = new ArrayList>();
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(fromInstruction, 0)));
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(fromInstruction, 1)));
    +		assertEquals(expected, replacements.values());
    +
    +		expected = new ArrayList>();
    +		expected.add(Arrays.asList(
    +				new Replacements.InstructionBranch(fromInstruction, 0),
    +				new Replacements.InstructionBranch(fromInstruction, 2)));
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(fromInstruction, 1)));
    +		replacements.add(target1, fromInstruction, 2);
    +		assertEquals(expected, replacements.values());
    +	}
    +
    +	@Test
    +	public void should_ignore_default_branch_of_LookupSwitch_instruction() {
    +		final LabelNode defaultLabel = new LabelNode();
    +		final LabelNode caseA = new LabelNode();
    +		final LabelNode caseB = new LabelNode();
    +		final LookupSwitchInsnNode switchNode = new LookupSwitchInsnNode(
    +				defaultLabel, // branch 0
    +				new int[] { 0, 1, 2, 3 }, new LabelNode[] { //
    +						caseA, // branch 1
    +						defaultLabel, // branch 0
    +						caseA, // branch 1
    +						caseB // branch 2
    +				});
    +		final ArrayList> expected = new ArrayList>();
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(switchNode, 1)));
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(switchNode, 2)));
    +		assertEquals(expected,
    +				Replacements.ignoreDefaultBranch(switchNode).values());
    +	}
    +
    +	@Test
    +	public void should_ignore_default_branch_of_TableSwitch_instruction() {
    +		final LabelNode defaultLabel = new LabelNode();
    +		final LabelNode caseA = new LabelNode();
    +		final LabelNode caseB = new LabelNode();
    +		final TableSwitchInsnNode switchNode = new TableSwitchInsnNode(0, 3,
    +				defaultLabel, // branch 0
    +				caseA, // branch 1
    +				defaultLabel, // branch 0
    +				caseA, // branch 1
    +				caseB // branch 2
    +		);
    +		final ArrayList> expected = new ArrayList>();
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(switchNode, 1)));
    +		expected.add(Collections.singletonList(
    +				new Replacements.InstructionBranch(switchNode, 2)));
    +		assertEquals(expected,
    +				Replacements.ignoreDefaultBranch(switchNode).values());
    +	}
    +
    +	private static  void assertEquals(final Iterable expected,
    +			final Iterable actual) {
    +		final Iterator e = expected.iterator();
    +		final Iterator a = actual.iterator();
    +		while (e.hasNext() && a.hasNext()) {
    +			Assert.assertEquals(e.next(), a.next());
    +		}
    +		Assert.assertEquals(e.hasNext(), a.hasNext());
    +	}
    +
    +	@Test
    +	public void test_InstructionBranch_equals_and_hashCode() {
    +		final InsnNode i1 = new InsnNode(Opcodes.NOP);
    +		final InsnNode i2 = new InsnNode(Opcodes.NOP);
    +		final Replacements.InstructionBranch ib = new Replacements.InstructionBranch(
    +				i1, 0);
    +		assertFalse(ib.equals(null));
    +		assertFalse(ib.equals(new Object()));
    +		assertFalse(ib.equals(new Replacements.InstructionBranch(i1, 1)));
    +		assertFalse(ib.equals(new Replacements.InstructionBranch(i2, 0)));
    +		assertTrue(ib.equals(new Replacements.InstructionBranch(i1, 0)));
    +		Assert.assertEquals(ib.hashCode(),
    +				new Replacements.InstructionBranch(i1, 0).hashCode());
    +	}
    +
    +}
    diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java
    index bfcf7f413b..f241d6c3c5 100644
    --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java
    +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java
    @@ -12,14 +12,12 @@
      *******************************************************************************/
     package org.jacoco.core.internal.analysis.filter;
     
    -import java.util.HashSet;
    -import java.util.Set;
    +import java.util.ArrayList;
     
     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;
     
     /**
    @@ -29,11 +27,11 @@ public class StringSwitchFilterTest extends FilterTestBase {
     
     	private final IFilter filter = new StringSwitchFilter();
     
    +	private final ArrayList replacements = new ArrayList();
    +
     	@Test
     	public void should_filter() {
     		final Range range = new Range();
    -		final Set expectedNewTargets = new HashSet();
    -
     		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     				"name", "()V", null, null);
     
    @@ -56,6 +54,7 @@ public void should_filter() {
     				"()I", false);
     		range.fromInclusive = m.instructions.getLast();
     		m.visitTableSwitchInsn(97, 98, caseDefault, h1, h2);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h1);
     
    @@ -65,6 +64,7 @@ public void should_filter() {
     				"(Ljava/lang/Object;)Z", false);
     		// if equal "a", then goto its case
     		m.visitJumpInsn(Opcodes.IFNE, case1);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 1));
     
     		m.visitVarInsn(Opcodes.ALOAD, 2);
     		m.visitLdcInsn("\0a");
    @@ -72,9 +72,11 @@ public void should_filter() {
     				"(Ljava/lang/Object;)Z", false);
     		// if equal "\0a", then goto its case
     		m.visitJumpInsn(Opcodes.IFNE, case2);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 1));
     
     		// goto default case
     		m.visitJumpInsn(Opcodes.GOTO, caseDefault);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h2);
     
    @@ -84,36 +86,32 @@ public void should_filter() {
     				"(Ljava/lang/Object;)Z", false);
     		// if equal "b", then goto its case
     		m.visitJumpInsn(Opcodes.IFNE, case3);
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 1));
     
     		// goto default case
     		m.visitJumpInsn(Opcodes.GOTO, caseDefault);
     		range.toInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(caseDefault);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(range.fromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, range.fromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	@Test
     	public void should_filter_when_default_is_first() {
     		final Range range = new Range();
    -		final Set expectedNewTargets = new HashSet();
    -
     		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     				"name", "()V", null, null);
     
    @@ -134,6 +132,7 @@ public void should_filter_when_default_is_first() {
     		range.fromInclusive = m.instructions.getLast();
     		m.visitLookupSwitchInsn(caseDefault, new int[] { 97 },
     				new Label[] { h1 });
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h1);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -143,19 +142,19 @@ public void should_filter_when_default_is_first() {
     		// if equal "a", then goto its case
     		m.visitJumpInsn(Opcodes.IFNE, case1);
     		range.toInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 1));
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(caseDefault);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(range.fromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, range.fromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	/**
    @@ -175,8 +174,6 @@ public void should_filter_when_default_is_first() {
     	@Test
     	public void should_filter_Kotlin_1_5() {
     		final Range range = new Range();
    -		final Set expectedNewTargets = new HashSet();
    -
     		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
     				"example", "()V", null, null);
     
    @@ -197,6 +194,7 @@ public void should_filter_Kotlin_1_5() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
     				"()I", false);
     		m.visitTableSwitchInsn(97, 99, defaultCase, h1, h2, h3);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h1);
     		m.visitVarInsn(Opcodes.ALOAD, 1);
    @@ -204,14 +202,17 @@ public void should_filter_Kotlin_1_5() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case1);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 1));
     
     		m.visitVarInsn(Opcodes.ALOAD, 1);
     		m.visitLdcInsn("\u0000a");
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case2);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 1));
     
     		m.visitJumpInsn(Opcodes.GOTO, defaultCase);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h2);
     		m.visitVarInsn(Opcodes.ALOAD, 1);
    @@ -219,14 +220,17 @@ public void should_filter_Kotlin_1_5() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case3);
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 1));
     
     		m.visitVarInsn(Opcodes.ALOAD, 1);
     		m.visitLdcInsn("\u0000b");
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case4);
    +		replacements.add(new Replacement(4, m.instructions.getLast(), 1));
     
     		m.visitJumpInsn(Opcodes.GOTO, defaultCase);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(h3);
     		m.visitVarInsn(Opcodes.ALOAD, 1);
    @@ -234,43 +238,39 @@ public void should_filter_Kotlin_1_5() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case5);
    +		replacements.add(new Replacement(5, m.instructions.getLast(), 1));
     
     		m.visitVarInsn(Opcodes.ALOAD, 1);
     		m.visitLdcInsn("\u0000c");
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, case6);
    +		replacements.add(new Replacement(6, m.instructions.getLast(), 1));
     
     		m.visitJumpInsn(Opcodes.GOTO, defaultCase);
     		range.toInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(case1);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case2);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case3);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case4);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case5);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(case6);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     		m.visitLabel(defaultCase);
     		m.visitInsn(Opcodes.RETURN);
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(range.fromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, range.fromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	/**
    @@ -286,8 +286,6 @@ public void should_filter_Kotlin_1_5() {
     	@Test
     	public void should_filter_Kotlin_nullable_else() {
     		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);
    @@ -305,11 +303,13 @@ public void should_filter_Kotlin_nullable_else() {
     		m.visitVarInsn(Opcodes.ALOAD, 2);
     		range.fromInclusive = m.instructions.getLast();
     		m.visitJumpInsn(Opcodes.IFNULL, caseElse);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 1));
     		m.visitVarInsn(Opcodes.ALOAD, 2);
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
     				"()I", false);
     		m.visitTableSwitchInsn(97, 99, caseElse,
     				new Label[] { hashA, hashB, hashC });
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashA);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -317,7 +317,9 @@ public void should_filter_Kotlin_nullable_else() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseA);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashB);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -325,7 +327,9 @@ public void should_filter_Kotlin_nullable_else() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseB);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashC);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -333,27 +337,25 @@ public void should_filter_Kotlin_nullable_else() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseC);
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
     		range.toInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		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(caseElse);
     		m.visitLdcInsn("else");
    -		expectedNewTargets.add(m.instructions.getLast());
     
     		m.visitLabel(end);
     		m.visitInsn(Opcodes.ARETURN);
    @@ -361,8 +363,8 @@ public void should_filter_Kotlin_nullable_else() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(range.fromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, range.fromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	/**
    @@ -379,8 +381,6 @@ public void should_filter_Kotlin_nullable_else() {
     	@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);
    @@ -400,10 +400,12 @@ public void should_filter_Kotlin_nullable_case() {
     		range.fromInclusive = m.instructions.getLast();
     		m.visitInsn(Opcodes.DUP);
     		m.visitJumpInsn(Opcodes.IFNULL, caseNull);
    +		replacements.add(new Replacement(4, m.instructions.getLast(), 1));
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
     				"()I", false);
     		m.visitTableSwitchInsn(97, 99, caseElse,
     				new Label[] { hashA, hashB, hashC });
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashA);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -411,7 +413,9 @@ public void should_filter_Kotlin_nullable_case() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseA);
    +		replacements.add(new Replacement(1, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashB);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -419,7 +423,9 @@ public void should_filter_Kotlin_nullable_case() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseB);
    +		replacements.add(new Replacement(2, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		m.visitLabel(hashC);
     		m.visitVarInsn(Opcodes.ALOAD, 2);
    @@ -427,33 +433,30 @@ public void should_filter_Kotlin_nullable_case() {
     		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
     				"(Ljava/lang/Object;)Z", false);
     		m.visitJumpInsn(Opcodes.IFNE, caseC);
    +		replacements.add(new Replacement(3, m.instructions.getLast(), 1));
     		m.visitJumpInsn(Opcodes.GOTO, caseElse);
     		range.toInclusive = m.instructions.getLast();
    +		replacements.add(new Replacement(0, m.instructions.getLast(), 0));
     
     		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);
    @@ -461,8 +464,8 @@ public void should_filter_Kotlin_nullable_case() {
     		filter.filter(m, context, output);
     
     		assertIgnored(range);
    -		assertReplacedBranches(range.fromInclusive.getPrevious(),
    -				expectedNewTargets);
    +		assertReplacedBranches(m, range.fromInclusive.getPrevious(),
    +				replacements);
     	}
     
     	@Test
    @@ -481,6 +484,7 @@ public void should_not_filter_empty_lookup_switch() {
     		filter.filter(m, context, output);
     
     		assertIgnored();
    +		assertNoReplacedBranches();
     	}
     
     }
    diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java
    index 5f9cb79bf8..963864431a 100644
    --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java
    +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java
    @@ -16,6 +16,8 @@
     import java.util.Collection;
     
     import org.jacoco.core.analysis.ICounter;
    +import org.jacoco.core.internal.analysis.filter.Replacements;
    +import org.objectweb.asm.tree.AbstractInsnNode;
     
     /**
      * Execution status of a single bytecode instruction internally used for
    @@ -50,7 +52,7 @@
      *
      * 
      *
    • {@link #merge(Instruction)}
    • - *
    • {@link #replaceBranches(Collection)}
    • + *
    • {@link #replaceBranches(Replacements, Mapper)}
    • *
    */ public class Instruction { @@ -160,26 +162,42 @@ public Instruction merge(final Instruction other) { /** * Creates a copy of this instruction where all outgoing branches are - * replaced with the given instructions. The coverage status of the new - * instruction is derived from the status of the given instructions. + * replaced. The coverage statuses of the branches of the new instruction + * are derived from the statuses of the given branches of the given + * instructions. * - * @param newBranches - * new branches to consider + * @param replacements + * new branches + * @param mapper + * provides {@link Instruction} corresponding to + * {@link Replacements.InstructionBranch#instruction} * @return new instance with replaced branches */ - public Instruction replaceBranches( - final Collection newBranches) { + public Instruction replaceBranches(final Replacements replacements, + final Mapper mapper) { final Instruction result = new Instruction(this.line); - result.branches = newBranches.size(); - int idx = 0; - for (final Instruction b : newBranches) { - if (!b.coveredBranches.isEmpty()) { - result.coveredBranches.set(idx++); + int branchIndex = 0; + for (final Collection newBranch : replacements + .values()) { + for (final Replacements.InstructionBranch from : newBranch) { + if (mapper.apply(from.instruction).coveredBranches + .get(from.branch)) { + result.coveredBranches.set(branchIndex); + } } + branchIndex++; } + result.branches = branchIndex; return result; } + /** + * {@code java.util.function.Function} + */ + interface Mapper { + Instruction apply(AbstractInsnNode node); + } + /** * Returns the instruction coverage counter of this instruction. It is * always 1 instruction which is covered or not. 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 6f4658b2db..4c5fcbef7f 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 @@ -12,16 +12,15 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.jacoco.core.analysis.ISourceNode; import org.jacoco.core.internal.analysis.filter.IFilterOutput; +import org.jacoco.core.internal.analysis.filter.Replacements; import org.objectweb.asm.tree.AbstractInsnNode; /** @@ -48,14 +47,14 @@ class MethodCoverageCalculator implements IFilterOutput { */ private final Map merged; - private final Map> replacements; + private final Map replacements; MethodCoverageCalculator( final Map instructions) { this.instructions = instructions; this.ignored = new HashSet(); this.merged = new HashMap(); - this.replacements = new HashMap>(); + this.replacements = new HashMap(); } /** @@ -105,17 +104,16 @@ private void applyMerges() { } private void applyReplacements() { - for (final Entry> entry : replacements - .entrySet()) { - final Set replacements = entry.getValue(); - final List newBranches = new ArrayList( - replacements.size()); - for (final AbstractInsnNode b : replacements) { - newBranches.add(instructions.get(b)); + final Instruction.Mapper mapper = new Instruction.Mapper() { + public Instruction apply(final AbstractInsnNode node) { + return instructions.get(node); } + }; + for (final Entry entry : replacements + .entrySet()) { final AbstractInsnNode node = entry.getKey(); - instructions.put(node, - instructions.get(node).replaceBranches(newBranches)); + instructions.put(node, instructions.get(node) + .replaceBranches(entry.getValue(), mapper)); } } @@ -171,8 +169,8 @@ public void merge(AbstractInsnNode i1, AbstractInsnNode i2) { } public void replaceBranches(final AbstractInsnNode source, - final Set newTargets) { - replacements.put(source, newTargets); + final Replacements replacements) { + this.replacements.put(source, replacements); } } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java index eaa2d58c1d..881284d3b1 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilter.java @@ -12,9 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.List; - import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.LabelNode; @@ -46,13 +43,10 @@ private static class Matcher extends AbstractMatcher { public void match(final AbstractInsnNode start, final int line, final IFilterOutput output) { final LabelNode dflt; - final List labels; if (start.getOpcode() == Opcodes.LOOKUPSWITCH) { dflt = ((LookupSwitchInsnNode) start).dflt; - labels = ((LookupSwitchInsnNode) start).labels; } else if (start.getOpcode() == Opcodes.TABLESWITCH) { dflt = ((TableSwitchInsnNode) start).dflt; - labels = ((TableSwitchInsnNode) start).labels; } else { return; } @@ -93,11 +87,8 @@ public void match(final AbstractInsnNode start, final int line, return; } output.ignore(dflt, cursor); - final HashSet replacements = new HashSet(); - for (final AbstractInsnNode label : labels) { - replacements.add(skipNonOpcodes(label)); - } - output.replaceBranches(start, replacements); + output.replaceBranches(start, + Replacements.ignoreDefaultBranch(start)); } private static AbstractInsnNode skipToLineNumberOrInstruction( diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java index 39066e6c0d..effd2ce965 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java @@ -12,8 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.Set; - import org.objectweb.asm.tree.AbstractInsnNode; /** @@ -50,10 +48,9 @@ public interface IFilterOutput { * * @param source * instruction which branches should be replaced - * @param newTargets - * new targets of branches + * @param replacements + * new branches */ - void replaceBranches(AbstractInsnNode source, - Set newTargets); + void replaceBranches(AbstractInsnNode source, Replacements replacements); } 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 index 50b7173467..e285687ed1 100644 --- 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 @@ -15,7 +15,6 @@ 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; @@ -36,12 +35,15 @@ public void filter(final MethodNode methodNode, if (chain.size() == 1) { continue; } - final 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); + final JumpInsnNode lastIfNullInstruction = chain + .get(chain.size() - 1); + final AbstractInsnNode nullTarget = AbstractMatcher + .skipNonOpcodes(lastIfNullInstruction.label); + final Replacements replacements = new Replacements(); + replacements.add(lastIfNullInstruction, lastIfNullInstruction, 0); + replacements.add(nullTarget, nullTarget, 0); + for (final AbstractInsnNode ifNullInstruction : chain) { + output.replaceBranches(ifNullInstruction, replacements); } } } 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 d082b93484..582a5fdaf1 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 @@ -12,10 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.FieldInsnNode; @@ -63,7 +59,8 @@ void match(final AbstractInsnNode start, final IFilterOutput output) { return; } else if (getDefaultLabel(i) == start) { - ignoreDefaultBranch(i, output); + output.replaceBranches(i, + Replacements.ignoreDefaultBranch(i)); output.ignore(start, cursor); return; @@ -116,22 +113,4 @@ private static LabelNode getDefaultLabel(final AbstractInsnNode i) { } } - private static void ignoreDefaultBranch(final AbstractInsnNode switchNode, - final IFilterOutput output) { - final List labels; - if (switchNode.getOpcode() == Opcodes.LOOKUPSWITCH) { - labels = ((LookupSwitchInsnNode) switchNode).labels; - } else { - labels = ((TableSwitchInsnNode) switchNode).labels; - } - final LabelNode defaultLabel = getDefaultLabel(switchNode); - final Set newTargets = new HashSet(); - for (final LabelNode label : labels) { - if (label != defaultLabel) { - newTargets.add(AbstractMatcher.skipNonOpcodes(label)); - } - } - output.replaceBranches(switchNode, newTargets); - } - } 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 f488c28d02..2296948335 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 @@ -12,9 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.Set; - import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.JumpInsnNode; @@ -71,8 +68,8 @@ public void match(final AbstractInsnNode start, return; } - final Set replacements = new HashSet(); - replacements.add(skipNonOpcodes(defaultLabel)); + final Replacements replacements = new Replacements(); + replacements.add(defaultLabel, s, 0); for (int i = 1; i <= hashCodes; i++) { while (true) { @@ -88,15 +85,17 @@ public void match(final AbstractInsnNode start, return; } else if (cursor.getOpcode() == Opcodes.GOTO) { // jump to case body - replacements.add( - skipNonOpcodes(((JumpInsnNode) cursor).label)); + replacements.add(((JumpInsnNode) cursor).label, cursor, + 0); if (jump.label == defaultLabel) { // end of comparisons for same hashCode + replacements.add(defaultLabel, jump, 1); break; } } else if (i == hashCodes && jump.label == defaultLabel) { // case body - replacements.add(cursor); + replacements.add(defaultLabel, jump, 1); + replacements.add(cursor, jump, 0); cursor = jump; break; } else { diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java new file mode 100644 index 0000000000..0a7a03c386 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.LinkedHashMap; +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; + +/** + * Utility for creating an argument for + * {@link IFilterOutput#replaceBranches(AbstractInsnNode, Replacements)} with + * information about how to compute the coverage status of branches of + * instruction from the coverage status of branches of other instructions. + */ +public final class Replacements { + + private final LinkedHashMap> newBranches = new LinkedHashMap>(); + + /** + * Adds branch which has a given target and which should be considered as + * covered when a branch with a given index of a given instruction is + * covered. + *

    + * The branch index should be specified in accordance with the ones assigned + * by {@link org.jacoco.core.internal.analysis.MethodAnalyzer} to a given + * instruction: + * + *

      + *
    • for {@link org.objectweb.asm.tree.TableSwitchInsnNode} (and similarly + * for {@link org.objectweb.asm.tree.LookupSwitchInsnNode}) + *
        + *
      • the branch index corresponds to the indexes in the list of unique + * labels among {@link org.objectweb.asm.tree.TableSwitchInsnNode#dflt} and + * {@link org.objectweb.asm.tree.TableSwitchInsnNode#labels}
      • + *
      • there are as many branches as unique labels
      • + *
      • branch 0 corresponds to continuation of execution at + * {@link org.objectweb.asm.tree.TableSwitchInsnNode#dflt}
      • + *
      + *
    • + * + *
    • for {@link org.objectweb.asm.tree.JumpInsnNode} with + * {@link org.objectweb.asm.Opcodes#GOTO} there is only branch 0 that + * corresponds to continuation of execution at + * {@link org.objectweb.asm.tree.JumpInsnNode#label}
    • + * + *
    • for other {@link org.objectweb.asm.tree.JumpInsnNode} there are two + * branches + *
        + *
      • branch 1 corresponds to continuation of execution at + * {@link org.objectweb.asm.tree.JumpInsnNode#label}
      • + *
      • branch 0 corresponds to continuation of execution at + * {@link AbstractInsnNode#getNext()}
      • + *
      + *
    • + * + *
    • for instructions with {@link org.objectweb.asm.Opcodes#RETURN} and + * {@link org.objectweb.asm.Opcodes#ATHROW} there is only branch 0 that + * corresponds to exit from the method
    • + * + *
    • there are no branches for instructions whose + * {@link AbstractInsnNode#getOpcode()} is -1
    • + * + *
    • for other instructions there is only branch 0 that corresponds to + * continuation of execution at {@link AbstractInsnNode#getNext()}
    • + *
    + * + * @param target + * instruction uniquely identifying new branch, e.g. its target + * @param instruction + * instruction whose branch execution status should be used + * @param branchIndex + * index of branch whose execution status should be used + */ + public void add(final AbstractInsnNode target, + final AbstractInsnNode instruction, final int branchIndex) { + Collection from = newBranches.get(target); + if (from == null) { + from = new ArrayList(); + newBranches.put(target, from); + } + from.add(new InstructionBranch(instruction, branchIndex)); + } + + /** + * @return the accumulated information in the order of + * {@link #add(AbstractInsnNode, AbstractInsnNode, int) additions} + */ + public Iterable> values() { + return newBranches.values(); + } + + /** + * @return information about how to compute coverage status of branches of a + * given {@link TableSwitchInsnNode} or {@link LookupSwitchInsnNode} + * in order to ignore its {@link TableSwitchInsnNode#dflt} or + * {@link LookupSwitchInsnNode#dflt} + */ + static Replacements ignoreDefaultBranch(final AbstractInsnNode switchNode) { + final List labels; + final LabelNode defaultLabel; + if (switchNode.getOpcode() == Opcodes.LOOKUPSWITCH) { + final LookupSwitchInsnNode s = (LookupSwitchInsnNode) switchNode; + labels = s.labels; + defaultLabel = s.dflt; + } else { + final TableSwitchInsnNode s = (TableSwitchInsnNode) switchNode; + labels = s.labels; + defaultLabel = s.dflt; + } + final Replacements replacements = new Replacements(); + int branchIndex = 0; + for (final LabelNode label : labels) { + if (label != defaultLabel + && replacements.newBranches.get(label) == null) { + branchIndex++; + replacements.add(label, switchNode, branchIndex); + } + } + return replacements; + } + + /** + * {@link #instruction} and index of its {@link #branch}. + */ + public static final class InstructionBranch { + /** Instruction. */ + public final AbstractInsnNode instruction; + /** Branch index. */ + public final int branch; + + /** + * Creates a new {@link InstructionBranch}. + * + * @param instruction + * instruction + * @param branch + * branch index + */ + public InstructionBranch(final AbstractInsnNode instruction, + final int branch) { + this.instruction = instruction; + this.branch = branch; + } + + @Override + public boolean equals(final Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + final InstructionBranch other = (InstructionBranch) o; + return this.instruction.equals(other.instruction) + && this.branch == other.branch; + } + + @Override + public int hashCode() { + return instruction.hashCode() * 31 + branch; + } + } + +} 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 427790bc85..17d62a802c 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 @@ -12,9 +12,6 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import java.util.HashSet; -import java.util.Set; - import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.JumpInsnNode; @@ -89,8 +86,8 @@ public void match(final AbstractInsnNode start, return; } - final Set replacements = new HashSet(); - replacements.add(skipNonOpcodes(defaultLabel)); + final Replacements replacements = new Replacements(); + replacements.add(defaultLabel, s, 0); for (int i = 0; i < hashCodes; i++) { while (true) { @@ -104,22 +101,23 @@ public void match(final AbstractInsnNode start, return; } - replacements - .add(skipNonOpcodes(((JumpInsnNode) cursor).label)); + replacements.add(((JumpInsnNode) cursor).label, cursor, 1); if (cursor.getNext().getOpcode() == Opcodes.GOTO) { // end of comparisons for same hashCode // jump to default nextIs(Opcodes.GOTO); + replacements.add(defaultLabel, cursor, 0); break; } else if (cursor.getNext() == defaultLabel) { + replacements.add(defaultLabel, cursor, 0); break; } } } if (ifNullInstruction != null) { - replacements.add(skipNonOpcodes(ifNullInstruction.label)); + replacements.add(ifNullInstruction.label, ifNullInstruction, 1); } output.ignore(start.getNext(), cursor); diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 42d8256d37..0d2a40cfee 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -27,6 +27,16 @@

    New Features

    (GitHub #1655). +

    Fixed bugs

    +
      +
    • Fixed handling of implicit else clause of when with + String subject in Kotlin + (GitHub #1813).
    • +
    • Fixed handling of implicit default clause of switch + by String in Java when compiled by ECJ + (GitHub #1813).
    • +
    +

    Release 0.8.13 (2025/04/02)

    New Features

    From bfa22da8da1994b226038c11f38592454afca9e1 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Fri, 11 Apr 2025 22:51:11 +0200 Subject: [PATCH 209/255] Improve `FilterTestBase.assertIgnored` (#1877) --- .../filter/AnnotationGeneratedFilterTest.java | 4 +- .../analysis/filter/AssertFilterTest.java | 6 +-- .../analysis/filter/BridgeFilterTest.java | 2 +- .../EnumEmptyConstructorFilterTest.java | 10 ++-- .../analysis/filter/EnumFilterTest.java | 6 +-- .../filter/ExhaustiveSwitchFilterTest.java | 8 +-- .../analysis/filter/FilterTestBase.java | 26 ++++++++-- .../analysis/filter/FilterTestBaseTest.java | 49 +++++++++++++++++++ .../filter/KotlinComposeFilterTest.java | 3 +- .../filter/KotlinCoroutineFilterTest.java | 10 ++-- .../KotlinDefaultArgumentsFilterTest.java | 19 ++++--- .../KotlinDefaultMethodsFilterTest.java | 4 +- .../analysis/filter/KotlinEnumFilterTest.java | 6 +-- .../filter/KotlinGeneratedFilterTest.java | 8 +-- .../filter/KotlinInlineClassFilterTest.java | 4 +- .../filter/KotlinInlineFilterTest.java | 10 ++-- .../filter/KotlinJvmOverloadsFilterTest.java | 4 +- .../filter/KotlinLateinitFilterTest.java | 22 ++++----- .../KotlinNotNullOperatorFilterTest.java | 2 +- .../KotlinSafeCallOperatorFilterTest.java | 4 +- .../filter/KotlinSyntheticFilterTest.java | 8 +-- .../KotlinUnsafeCastOperatorFilterTest.java | 8 +-- .../analysis/filter/KotlinWhenFilterTest.java | 12 ++--- .../filter/KotlinWhenStringFilterTest.java | 6 +-- .../filter/RecordPatternFilterTest.java | 4 +- .../analysis/filter/RecordsFilterTest.java | 20 ++++---- .../filter/StringSwitchFilterTest.java | 12 ++--- .../filter/StringSwitchJavacFilterTest.java | 8 +-- .../filter/SynchronizedFilterTest.java | 6 +-- .../analysis/filter/SyntheticFilterTest.java | 8 +-- .../filter/TryWithResourcesEcjFilterTest.java | 4 +- .../TryWithResourcesJavac11FilterTest.java | 4 +- .../TryWithResourcesJavacFilterTest.java | 8 +-- 33 files changed, 193 insertions(+), 122 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBaseTest.java diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java index 037a367160..bee06a066d 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java @@ -107,7 +107,7 @@ public void should_not_filter_when_no_annotations() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -123,7 +123,7 @@ public void should_not_filter_when_other_annotations() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AssertFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AssertFilterTest.java index d703b0e005..81ffd70339 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AssertFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AssertFilterTest.java @@ -63,7 +63,7 @@ public void should_filter_static_initializer() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); } /** @@ -99,7 +99,7 @@ public void should_not_filter_static_initializer_when_field_name_does_not_match( filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -139,7 +139,7 @@ public void should_filter_assert() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/BridgeFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/BridgeFilterTest.java index 1b86857f9b..b189e28bc4 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/BridgeFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/BridgeFilterTest.java @@ -43,7 +43,7 @@ public void should_not_filter_non_bridge_methods() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java index 8a1ffffee4..1ef943a5d9 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java @@ -39,7 +39,7 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored( + assertIgnored(m, new Range(m.instructions.getFirst(), m.instructions.getLast())); } @@ -69,7 +69,7 @@ public void should_not_filter_non_empty_constructor() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -96,7 +96,7 @@ public void should_not_filter_constructor_with_additional_parameters() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -118,7 +118,7 @@ public void should_not_filter_non_constructor() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -130,7 +130,7 @@ public void should_not_filter_non_Enum() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java index 0c7f901f96..1c3acfb324 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java @@ -44,7 +44,7 @@ public void testNonValues() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -68,7 +68,7 @@ public void testNonValueOf() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -79,7 +79,7 @@ public void testNonEnum() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java index d3d4e4c3d9..fd61fb0654 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/ExhaustiveSwitchFilterTest.java @@ -99,7 +99,7 @@ public void should_filter_when_default_branch_has_LineNumber_of_switch() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, switchNode, replacements); } @@ -171,7 +171,7 @@ public void should_filter_when_default_branch_has_no_LineNumber() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, switchNode, replacements); } @@ -244,7 +244,7 @@ public void should_filter_when_default_branch_throws_Java_21_MatchException() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, switchNode, replacements); } @@ -306,7 +306,7 @@ public void should_not_filter_when_default_branch_has_LineNumber_different_from_ filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } 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 7e27582131..3a2d7ce4ea 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 @@ -12,12 +12,12 @@ *******************************************************************************/ package org.jacoco.core.internal.analysis.filter; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -59,12 +59,30 @@ public void replaceBranches(AbstractInsnNode source, } }; - final void assertIgnored(Range... ranges) { - assertArrayEquals(ranges, ignoredRanges.toArray(new Range[0])); + final void assertIgnored(final MethodNode methodNode, + final Range... expected) { + assertEquals("ignored ranges", + rangesToString(methodNode, Arrays.asList(expected)), + rangesToString(methodNode, ignoredRanges)); + } + + private static String rangesToString(final MethodNode m, + final List ranges) { + final StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < ranges.size(); i++) { + final Range range = ranges.get(i); + stringBuilder.append("range ").append(i) + .append(" from instruction ") + .append(m.instructions.indexOf(range.fromInclusive)) + .append(" to ") + .append(m.instructions.indexOf(range.toInclusive)) + .append("\n"); + } + return stringBuilder.toString(); } final void assertMethodIgnored(final MethodNode m) { - assertIgnored( + assertIgnored(m, new Range(m.instructions.getFirst(), m.instructions.getLast())); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBaseTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBaseTest.java new file mode 100644 index 0000000000..cefdf8c91f --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBaseTest.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.jacoco.core.internal.instr.InstrSupport; +import org.junit.ComparisonFailure; +import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link FilterTestBase}. + */ +public class FilterTestBaseTest extends FilterTestBase { + + @Test + public void assertIgnored_should_throw_ComparisonFailure() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "()V", null, null); + final Range range = new Range(); + m.visitInsn(Opcodes.NOP); + range.fromInclusive = m.instructions.getFirst(); + range.toInclusive = m.instructions.getLast(); + + try { + assertIgnored(m, range); + fail("exception expected"); + } catch (final ComparisonFailure e) { + assertEquals("", e.getActual()); + assertEquals("range 0 from instruction 0 to 0\n", e.getExpected()); + assertTrue(e.getMessage().startsWith("ignored ranges expected:")); + } + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java index ca9d244ff6..7df4b8bcfd 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java @@ -249,7 +249,8 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(range1, range2, range3, range4, range5, range6, range7); + assertIgnored(m, range1, range2, range3, range4, range5, range6, + range7); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java index 8f8d0abe63..ab906df8f4 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java @@ -107,7 +107,7 @@ public void should_filter_suspending_lambdas_generated_by_Kotlin_1_3_30() { filter.filter(m, context, output); - assertIgnored(range0, range1, range2); + assertIgnored(m, range0, range1, range2); } /** @@ -218,7 +218,7 @@ public void should_filter_suspending_lambdas() { filter.filter(m, context, output); - assertIgnored(range0, range1, range2); + assertIgnored(m, range0, range1, range2); } /** @@ -369,7 +369,7 @@ public void should_filter_suspending_functions() { filter.filter(m, context, output); - assertIgnored(range0, range1, range2); + assertIgnored(m, range0, range1, range2); } /** @@ -445,7 +445,7 @@ public void should_filter_suspending_functions_with_tail_call_optimization() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } /** @@ -508,7 +508,7 @@ public void should_filter_Kotlin_1_6_suspending_lambda_without_suspension_points filter.filter(m, context, output); - assertIgnored(range0, range1); + assertIgnored(m, range0, range1); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java index 72ddb054fe..b608534c2d 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java @@ -60,7 +60,8 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + assertIgnored(m, + new Range(m.instructions.get(3), m.instructions.get(3))); } @Test @@ -72,7 +73,7 @@ public void should_not_filter_when_suffix_absent() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -84,7 +85,7 @@ public void should_not_filter_when_not_synthetic() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -137,7 +138,7 @@ public void should_filter_open_functions() { filter.filter(m, context, output); - assertIgnored( + assertIgnored(m, new Range(m.instructions.getFirst(), m.instructions.get(6)), new Range(m.instructions.get(11), m.instructions.get(11))); } @@ -173,7 +174,8 @@ public void should_filter_constructors() { filter.filter(m, context, output); - assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + assertIgnored(m, + new Range(m.instructions.get(3), m.instructions.get(3))); } /** @@ -207,7 +209,8 @@ public void should_filter_methods_with_parameters_that_consume_two_slots() { filter.filter(m, context, output); - assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3))); + assertIgnored(m, + new Range(m.instructions.get(3), m.instructions.get(3))); } /** @@ -271,7 +274,7 @@ public void should_filter_methods_with_more_than_32_parameters() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } /** @@ -346,7 +349,7 @@ public void should_filter_methods_with_more_than_224_parameters() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } @Test diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java index 5c1d989a2b..287a758199 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultMethodsFilterTest.java @@ -53,7 +53,7 @@ public void should_not_filter_when_invokestatic_owner_does_not_match() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -66,7 +66,7 @@ public void should_not_filter_when_instructions_do_not_match() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java index 4424fece58..278dedde5c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinEnumFilterTest.java @@ -58,7 +58,7 @@ public void should_not_filter_when_not_Enum() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -75,7 +75,7 @@ public void should_not_filter_when_not_getEntries_name() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -92,7 +92,7 @@ public void should_not_filter_when_not_getEntries_descriptor() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java index 7d60215cd6..b16f30384f 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java @@ -52,7 +52,7 @@ public void testWithLinesForKotlinWithDebug() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -67,7 +67,7 @@ public void testNoLinesForKotlinNoDebug() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -83,7 +83,7 @@ public void testWithLinesForKotlinNoDebug() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -110,7 +110,7 @@ public void should_filter_instructions_without_line_numbers() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java index c8dfcc9605..b149d8008e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineClassFilterTest.java @@ -62,7 +62,7 @@ public void should_not_filter_static() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -80,7 +80,7 @@ public void should_not_filter_when_no_JvmInline_annotation() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } 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 e981ccf925..ccd820ea23 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 @@ -85,7 +85,7 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(expectedRanges.toArray(new Range[0])); + assertIgnored(m, expectedRanges.toArray(new Range[0])); // should not reparse: context.sourceDebugExtension = ""; @@ -160,7 +160,7 @@ public void should_filter_when_in_same_file() { filter.filter(m, context, output); - assertIgnored(expectedRanges.toArray(new Range[0])); + assertIgnored(m, expectedRanges.toArray(new Range[0])); } /** @@ -218,7 +218,7 @@ public void should_filter_when_inlined_with_same_file_name_and_line_number() { filter.filter(m, context, output); - assertIgnored(expectedRanges.toArray(new Range[0])); + assertIgnored(m, expectedRanges.toArray(new Range[0])); } /** @@ -281,7 +281,7 @@ public void should_filter_all_lines() { filter.filter(m, context, output); - assertIgnored(expectedRanges.toArray(new Range[0])); + assertIgnored(m, expectedRanges.toArray(new Range[0])); } @Test @@ -294,7 +294,7 @@ public void should_not_filter_when_no_SourceDebugExtension_attribute() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } private final List expectedRanges = new ArrayList(); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinJvmOverloadsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinJvmOverloadsFilterTest.java index bd36503588..aec4ba6cc0 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinJvmOverloadsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinJvmOverloadsFilterTest.java @@ -176,7 +176,7 @@ public void should_not_filter_non_generated_functions() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -217,7 +217,7 @@ public void should_not_filter_non_generated_freestanding_functions() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } 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 79e6e13b35..ef71f7678c 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 @@ -43,7 +43,7 @@ public void should_filter_Kotlin_1_2() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -76,7 +76,7 @@ public void should_filter_Kotlin_1_5_0_public() { filter.filter(m, context, output); - assertIgnored(new Range(branch, branch), + assertIgnored(m, new Range(branch, branch), new Range(expectedFrom, expectedTo)); } @@ -109,7 +109,7 @@ public void should_filter_Kotlin_1_5_0_private() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -142,7 +142,7 @@ public void should_filter_Kotlin_1_5_30_public() { filter.filter(m, context, output); - assertIgnored(new Range(branch, branch), + assertIgnored(m, new Range(branch, branch), new Range(expectedFrom, expectedTo)); } @@ -177,7 +177,7 @@ public void should_filter_Kotlin_1_5_30_public_generic() { filter.filter(m, context, output); - assertIgnored(new Range(branch, branch), + assertIgnored(m, new Range(branch, branch), new Range(expectedFrom, expectedTo)); } @@ -212,7 +212,7 @@ public void should_filter_Kotlin_1_5_30_private() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -247,7 +247,7 @@ public void should_filter_Kotlin_1_5_30_private_generic() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -277,7 +277,7 @@ public void should_filter_Kotlin_1_6_0_private() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -308,7 +308,7 @@ public void should_filter_Kotlin_1_6_0_private_generic() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -340,7 +340,7 @@ public void should_filter_Kotlin_1_6_20_public() { filter.filter(m, context, output); - assertIgnored(new Range(branch, branch), + assertIgnored(m, new Range(branch, branch), new Range(expectedFrom, expectedTo)); } @@ -374,7 +374,7 @@ public void should_filter_Kotlin_1_6_20_public_generic() { filter.filter(m, context, output); - assertIgnored(new Range(branch, branch), + assertIgnored(m, new Range(branch, branch), new Range(expectedFrom, expectedTo)); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java index 69d431c3ac..1231e39b4b 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java @@ -54,7 +54,7 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, 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 index 2c6455fc8d..bcec3d98ef 100644 --- 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 @@ -71,7 +71,7 @@ public void should_filter_optimized_safe_call_chain() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); final HashMap> replacements = new HashMap>(); replacements.put(ifNullInstruction1, Arrays.asList( // new Replacement(0, ifNullInstruction2, 0), @@ -124,7 +124,7 @@ public void should_filter_unoptimized_safe_call_chain() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); final HashMap> replacements = new HashMap>(); replacements.put(ifNullInstruction1, Arrays.asList( // new Replacement(0, ifNullInstruction2, 0), diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java index b1bb1e130f..7042600e12 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSyntheticFilterTest.java @@ -43,7 +43,7 @@ public void should_not_filter_synthetic_non_accessor_methods_in_Kotlin_classes() filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -88,7 +88,7 @@ public void should_not_filter_method_with_suffix_default_in_kotlin_classes() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -103,7 +103,7 @@ public void should_not_filter_synthetic_constructor_containing_default_arguments filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** @@ -129,7 +129,7 @@ public void should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_co filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } /** diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index 6aebd16f62..6b555a9a6c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -49,7 +49,7 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } @Test @@ -73,7 +73,7 @@ public void should_filter_Kotlin_1_4() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } /** @@ -118,7 +118,7 @@ public void should_filter_Kotlin_1_5() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } @Test @@ -143,7 +143,7 @@ public void should_filter_Kotlin_1_6() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFrom, expectedTo)); + assertIgnored(m, new Range(expectedFrom, expectedTo)); } } 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 1d87f1d28f..918500e6c4 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 @@ -59,7 +59,7 @@ public void should_filter_implicit_else() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); assertNoReplacedBranches(); } @@ -83,7 +83,7 @@ public void should_not_filter_explicit_else() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); assertNoReplacedBranches(); } @@ -117,7 +117,7 @@ public void should_filter_implicit_default() { filter.filter(m, context, output); - assertIgnored(range1); + assertIgnored(m, range1); assertReplacedBranches(m, switchNode, replacements); } @@ -198,7 +198,7 @@ public void should_filter_when_by_nullable_enum_with_null_case_and_without_else( filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); assertReplacedBranches(m, switchNode, replacements); } @@ -258,7 +258,7 @@ public void should_filter_when_by_nullable_enum_without_null_case_and_with_else( filter.filter(m, context, output); - assertIgnored(range1); + assertIgnored(m, range1); assertNoReplacedBranches(); } @@ -318,7 +318,7 @@ public void should_filter_when_by_nullable_enum_with_null_and_else_cases() { filter.filter(m, context, output); - assertIgnored(range1); + assertIgnored(m, range1); assertNoReplacedBranches(); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java index 0cd7fd9a41..b1d0ef027a 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java @@ -104,7 +104,7 @@ public void should_filter() { assertReplacedBranches(m, expectedFromInclusive.getPrevious(), replacements); - assertIgnored(new Range(expectedFromInclusive, expectedToInclusive)); + assertIgnored(m, new Range(expectedFromInclusive, expectedToInclusive)); } /** @@ -178,7 +178,7 @@ public void should_filter_when_biggest_hashCode_first() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFromInclusive, expectedToInclusive)); + assertIgnored(m, new Range(expectedFromInclusive, expectedToInclusive)); assertReplacedBranches(m, expectedFromInclusive.getPrevious(), replacements); } @@ -197,7 +197,7 @@ public void should_not_filter_empty_lookup_switch() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordPatternFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordPatternFilterTest.java index 57f495079c..ae3045857f 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordPatternFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordPatternFilterTest.java @@ -107,7 +107,7 @@ public void should_filter_instanceof() { filter.filter(m, context, output); - assertIgnored(range, range); + assertIgnored(m, range, range); } /** @@ -214,7 +214,7 @@ public void should_filter_switch() { filter.filter(m, context, output); - assertIgnored(range, range); + assertIgnored(m, range, range); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordsFilterTest.java index 46e5c5f043..f41706d729 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordsFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/RecordsFilterTest.java @@ -53,7 +53,7 @@ public void should_not_filter_custom_toString_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -65,7 +65,7 @@ public void should_not_filter_non_toString_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -96,7 +96,7 @@ public void should_not_filter_custom_hashCode_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -108,7 +108,7 @@ public void should_not_filter_non_hashCode_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -140,7 +140,7 @@ public void should_not_filter_custom_equals_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -152,7 +152,7 @@ public void should_not_filter_non_equals_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -169,7 +169,7 @@ public void should_not_filter_non_records() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -212,7 +212,7 @@ public void should_not_filter_redirect_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -225,7 +225,7 @@ public void should_not_filter_noreturn_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -240,6 +240,6 @@ public void should_not_filter_other_method() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java index f241d6c3c5..53e633b0c6 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java @@ -104,7 +104,7 @@ public void should_filter() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, range.fromInclusive.getPrevious(), replacements); } @@ -152,7 +152,7 @@ public void should_filter_when_default_is_first() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, range.fromInclusive.getPrevious(), replacements); } @@ -268,7 +268,7 @@ public void should_filter_Kotlin_1_5() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, range.fromInclusive.getPrevious(), replacements); } @@ -362,7 +362,7 @@ public void should_filter_Kotlin_nullable_else() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, range.fromInclusive.getPrevious(), replacements); } @@ -463,7 +463,7 @@ public void should_filter_Kotlin_nullable_case() { filter.filter(m, context, output); - assertIgnored(range); + assertIgnored(m, range); assertReplacedBranches(m, range.fromInclusive.getPrevious(), replacements); } @@ -483,7 +483,7 @@ public void should_not_filter_empty_lookup_switch() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); assertNoReplacedBranches(); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java index 404dd79001..a6f05561a8 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java @@ -99,7 +99,7 @@ public void should_filter_code_generated_by_javac() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFromInclusive, expectedToInclusive)); + assertIgnored(m, new Range(expectedFromInclusive, expectedToInclusive)); } @Test @@ -112,7 +112,7 @@ public void should_filter_when_javac_generates_lookupswitch() { filter.filter(m, context, output); - assertIgnored(new Range(expectedFromInclusive, expectedToInclusive)); + assertIgnored(m, new Range(expectedFromInclusive, expectedToInclusive)); } /** @@ -163,7 +163,7 @@ public void should_not_filter_when_no_expected_goto() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -210,7 +210,7 @@ public void should_not_filter_code_generated_by_ECJ() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java index 71ee79f5b7..ce190a5a46 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java @@ -62,7 +62,7 @@ public void javac() { filter.filter(m, context, output); - assertIgnored(new Range((LabelNode) handler.info, + assertIgnored(m, new Range((LabelNode) handler.info, ((LabelNode) exit.info).getPrevious())); } @@ -116,7 +116,7 @@ public void javacTryCatchFinally() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -152,7 +152,7 @@ public void ecj() { filter.filter(m, context, output); - assertIgnored(new Range((LabelNode) handler.info, + assertIgnored(m, new Range((LabelNode) handler.info, ((LabelNode) exit.info).getPrevious())); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java index 8dc20f2999..cce75b88a3 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java @@ -32,7 +32,7 @@ public void testNonSynthetic() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -54,7 +54,7 @@ public void testLambda() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -75,7 +75,7 @@ public void should_not_filter_synthetic_method_with_prefix_anonfun_in_Scala_clas context.classAttributes.add("ScalaSig"); filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test @@ -86,7 +86,7 @@ public void should_not_filter_synthetic_method_with_prefix_anonfun_in_Scala_inne context.classAttributes.add("Scala"); filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } @Test diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java index 98aedb0124..8f013c488b 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java @@ -309,7 +309,7 @@ public void ecj() { filter.filter(m, context, output); - assertIgnored(range0, range1); + assertIgnored(m, range0, range1); } /** @@ -591,7 +591,7 @@ public void ecj_noFlowOut() { filter.filter(m, context, output); - assertIgnored(range0, range1); + assertIgnored(m, range0, range1); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java index 323f60467b..45d46d56d5 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java @@ -77,7 +77,7 @@ public void without_null_check() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } /** @@ -133,7 +133,7 @@ public void with_null_check() { filter.filter(m, context, output); - assertIgnored(range1, range2); + assertIgnored(m, range1, range2); } } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java index 9937463340..fbb180bbc2 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java @@ -218,7 +218,7 @@ public void javac9() { filter.filter(m, context, output); - assertIgnored(range0, range1, range2, range3); + assertIgnored(m, range0, range1, range2, range3); } /** @@ -535,7 +535,7 @@ public void javac_7_8() { filter.filter(m, context, output); - assertIgnored(range0, range1, range2, range3); + assertIgnored(m, range0, range1, range2, range3); } /** @@ -701,7 +701,7 @@ public void javac9_omitted_null_check() { filter.filter(m, context, output); - assertIgnored(range0, range1); + assertIgnored(m, range0, range1); } /** @@ -763,7 +763,7 @@ public void only_exceptional_path() { filter.filter(m, context, output); - assertIgnored(); + assertIgnored(m); } } From c3009f14265fe54d1f048f34bb0b4c0cdbe0812f Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:12:11 +0200 Subject: [PATCH 210/255] Improve KotlinSafeCallOperatorFilter for the cases when chain of safe call operators throws exception (#1819) --- .../kotlin/targets/KotlinSafeCallOperatorTarget.kt | 13 +++++++++++++ .../filter/KotlinSafeCallOperatorFilterTest.java | 4 ++-- .../filter/KotlinSafeCallOperatorFilter.java | 6 +++--- org.jacoco.doc/docroot/doc/changes.html | 2 ++ 4 files changed, 20 insertions(+), 5 deletions(-) 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 176f5d05cd..1cd372bb50 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,6 +13,8 @@ package org.jacoco.core.test.validation.kotlin.targets import org.jacoco.core.test.validation.targets.Stubs.nop +import org.jacoco.core.test.validation.targets.Stubs.StubException +import org.jacoco.core.test.validation.targets.Stubs.ex /** * Test target for [safe call operator (`?.`)](https://kotlinlang.org/docs/null-safety.html#safe-call-operator). @@ -76,11 +78,22 @@ object KotlinSafeCallOperatorTarget { fullCoverage(A(B(""))) } + private fun safeCallChainException() { + fun example(a: A?): String? = + a?.also { ex() }?.b?.c // assertPartlyCovered(3, 1) + + try { + example(A(B(""))) + } catch (_: StubException) { + } + } + @JvmStatic fun main(args: Array) { safeCall() safeCallChain() safeCallChainMultiline() + safeCallChainException() } } 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 index bcec3d98ef..718e706345 100644 --- 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 @@ -74,7 +74,7 @@ public void should_filter_optimized_safe_call_chain() { assertIgnored(m); final HashMap> replacements = new HashMap>(); replacements.put(ifNullInstruction1, Arrays.asList( // - new Replacement(0, ifNullInstruction2, 0), + new Replacement(0, ifNullInstruction1, 0), new Replacement(1, popInstruction, 0))); replacements.put(ifNullInstruction2, Arrays.asList( // new Replacement(0, ifNullInstruction2, 0), @@ -127,7 +127,7 @@ public void should_filter_unoptimized_safe_call_chain() { assertIgnored(m); final HashMap> replacements = new HashMap>(); replacements.put(ifNullInstruction1, Arrays.asList( // - new Replacement(0, ifNullInstruction2, 0), + new Replacement(0, ifNullInstruction1, 0), new Replacement(1, aconstNullInstruction, 0))); replacements.put(ifNullInstruction2, Arrays.asList( // new Replacement(0, ifNullInstruction2, 0), 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 index e285687ed1..9b272e765c 100644 --- 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 @@ -39,10 +39,10 @@ public void filter(final MethodNode methodNode, .get(chain.size() - 1); final AbstractInsnNode nullTarget = AbstractMatcher .skipNonOpcodes(lastIfNullInstruction.label); - final Replacements replacements = new Replacements(); - replacements.add(lastIfNullInstruction, lastIfNullInstruction, 0); - replacements.add(nullTarget, nullTarget, 0); for (final AbstractInsnNode ifNullInstruction : chain) { + final Replacements replacements = new Replacements(); + replacements.add(ifNullInstruction, ifNullInstruction, 0); + replacements.add(nullTarget, nullTarget, 0); output.replaceBranches(ifNullInstruction, replacements); } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 0d2a40cfee..a1e696a8f4 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -35,6 +35,8 @@

    Fixed bugs

  • Fixed handling of implicit default clause of switch by String in Java when compiled by ECJ (GitHub #1813).
  • +
  • Fixed handling of exceptions in chains of safe call operators in Kotlin + (GitHub #1819).
  • Release 0.8.13 (2025/04/02)

    From 46d72fd43775475e890772b85fc5b63374621ab8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:54:14 +0200 Subject: [PATCH 211/255] Bump actions/setup-java from 4.7.0 to 4.7.1 (#1881) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.0 to 4.7.1. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/3a4f6e1af504cf6a31855fa899c6aa5355ba6c12...c5195efecf7bdfc987ee8bae7a71cb8b11521c00) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 4.7.1 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 b3bd8186a6..240ea5a4a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 + - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 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@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 + - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'zulu' java-version: | From cc405660d33b394c840952d7f5cf2e45f2bb2637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 22:45:00 +0000 Subject: [PATCH 212/255] Upgrade spotless-maven-plugin to 2.44.4 (#1882) Bump com.diffplug.spotless:spotless-maven-plugin in /org.jacoco.build Bumps [com.diffplug.spotless:spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.44.3 to 2.44.4. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/maven/2.44.3...maven/2.44.4) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-version: 2.44.4 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 ecc6a28596..67512a72ce 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.44.3 + 2.44.4 org.sonarsource.scanner.maven From 11e90b737bca19e4c90c84ff1191b8e11249b70d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 13 May 2025 16:32:58 +0100 Subject: [PATCH 213/255] In Kotlin elvis operator that follows safe call operator should be filtered (#1814) --- .../targets/KotlinSafeCallOperatorTarget.kt | 34 +++++++ .../KotlinSafeCallOperatorFilterTest.java | 95 +++++++++++++++++++ .../filter/KotlinSafeCallOperatorFilter.java | 15 ++- org.jacoco.doc/docroot/doc/changes.html | 3 + 4 files changed, 143 insertions(+), 4 deletions(-) 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 1cd372bb50..2f55b3dd5f 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 @@ -88,12 +88,46 @@ object KotlinSafeCallOperatorTarget { } } + private fun safeCallFollowedByElvis() { + fun nullOnly(b: B?): String = + b?.c ?: "" // assertPartlyCovered(2, 2) + + fun nonNullOnly(b: B?): String = + b?.c ?: "" // assertPartlyCovered(2, 2) + + fun fullCoverage(b: B?): String = + b?.c ?: "" // assertFullyCovered(0, 4) + + nullOnly(null) + nonNullOnly(B("")) + fullCoverage(null) + fullCoverage(B("")) + } + + private fun safeCallChainFollowedByElvis() { + fun nullOnly(a: A?): String = + a?.b?.c ?: "" // assertPartlyCovered(3, 3) + + fun nonNullOnly(a: A?): String = + a?.b?.c ?: "" // assertPartlyCovered(3, 3) + + fun fullCoverage(a: A?): String = + a?.b?.c ?: "" // assertFullyCovered(0, 6) + + nullOnly(null) + nonNullOnly(A(B(""))) + fullCoverage(null) + fullCoverage(A(B(""))) + } + @JvmStatic fun main(args: Array) { safeCall() safeCallChain() safeCallChainMultiline() safeCallChainException() + safeCallFollowedByElvis() + safeCallChainFollowedByElvis() } } 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 index 718e706345..4a222a6ec7 100644 --- 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 @@ -135,4 +135,99 @@ public void should_filter_unoptimized_safe_call_chain() { assertReplacedBranches(m, replacements); } + /** + *
    +	 * data class B(val c: String)
    +	 * fun example(b: B?): String =
    +	 *     b?.c ?: ""
    +	 * 
    + */ + @Test + public void should_filter_safe_call_followed_by_elvis() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "(LB;)Ljava/lang/String;", null, null); + m.visitVarInsn(Opcodes.ALOAD, 0); + final Label label1 = new Label(); + final Label label2 = new Label(); + + m.visitInsn(Opcodes.DUP); + m.visitJumpInsn(Opcodes.IFNULL, label1); + final AbstractInsnNode ifNullInstruction = m.instructions.getLast(); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC", + "()Ljava/lang/String;", false); + + m.visitInsn(Opcodes.DUP); + m.visitJumpInsn(Opcodes.IFNONNULL, label2); + final AbstractInsnNode ifNonNullInstruction = m.instructions.getLast(); + m.visitLabel(label1); + m.visitInsn(Opcodes.POP); + final AbstractInsnNode popInstruction = m.instructions.getLast(); + m.visitLdcInsn(""); + m.visitLabel(label2); + + filter.filter(m, context, output); + + assertIgnored(m); + final HashMap> replacements = new HashMap>(); + replacements.put(ifNullInstruction, Arrays.asList( // + new Replacement(0, ifNullInstruction, 0), + new Replacement(1, popInstruction, 0))); + replacements.put(ifNonNullInstruction, Arrays.asList( // + new Replacement(0, popInstruction, 0), + new Replacement(1, ifNonNullInstruction, 1))); + assertReplacedBranches(m, replacements); + } + + /** + *
    +	 * data class A(val b: B)
    +	 * data class B(val c: String)
    +	 * fun example(a: A?): String =
    +	 *     a?.b?.c ?: ""
    +	 * 
    + */ + @Test + public void should_filter_safe_call_chain_followed_by_elvis() { + 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 ifNullInstruction1 = m.instructions.getLast(); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "A", "getB", "()LB;", false); + + m.visitInsn(Opcodes.DUP); + m.visitJumpInsn(Opcodes.IFNULL, label1); + final AbstractInsnNode ifNullInstruction2 = m.instructions.getLast(); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC", + "()Ljava/lang/String;", false); + + m.visitInsn(Opcodes.DUP); + m.visitJumpInsn(Opcodes.IFNONNULL, label2); + final AbstractInsnNode ifNonNullInstruction = m.instructions.getLast(); + m.visitLabel(label1); + m.visitInsn(Opcodes.POP); + final AbstractInsnNode popInstruction = m.instructions.getLast(); + m.visitLdcInsn(""); + m.visitLabel(label2); + + filter.filter(m, context, output); + + assertIgnored(m); + final HashMap> replacements = new HashMap>(); + replacements.put(ifNullInstruction1, Arrays.asList( // + new Replacement(0, ifNullInstruction1, 0), + new Replacement(1, popInstruction, 0))); + replacements.put(ifNullInstruction2, Arrays.asList( // + new Replacement(0, ifNullInstruction2, 0), + new Replacement(1, popInstruction, 0))); + replacements.put(ifNonNullInstruction, Arrays.asList( // + new Replacement(0, popInstruction, 0), + new Replacement(1, ifNonNullInstruction, 1))); + assertReplacedBranches(m, replacements); + } + } 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 index 9b272e765c..8fce63c698 100644 --- 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 @@ -32,19 +32,26 @@ final class KotlinSafeCallOperatorFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { for (final ArrayList chain : findChains(methodNode)) { - if (chain.size() == 1) { + final AbstractInsnNode ifNonNullInstruction = chain.get(0).label + .getPrevious(); + if (chain.size() == 1 + && ifNonNullInstruction.getOpcode() != Opcodes.IFNONNULL) { continue; } - final JumpInsnNode lastIfNullInstruction = chain - .get(chain.size() - 1); final AbstractInsnNode nullTarget = AbstractMatcher - .skipNonOpcodes(lastIfNullInstruction.label); + .skipNonOpcodes(chain.get(0).label); for (final AbstractInsnNode ifNullInstruction : chain) { final Replacements replacements = new Replacements(); replacements.add(ifNullInstruction, ifNullInstruction, 0); replacements.add(nullTarget, nullTarget, 0); output.replaceBranches(ifNullInstruction, replacements); } + if (ifNonNullInstruction.getOpcode() == Opcodes.IFNONNULL) { + final Replacements replacements = new Replacements(); + replacements.add(nullTarget, nullTarget, 0); + replacements.add(ifNonNullInstruction, ifNonNullInstruction, 1); + output.replaceBranches(ifNonNullInstruction, replacements); + } } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index a1e696a8f4..a1fd430b3c 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -25,6 +25,9 @@

    New Features

  • Branches added by the Kotlin compiler for default argument number 33 or higher are filtered out during generation of report (GitHub #1655).
  • +
  • Part of bytecode generated by the Kotlin compiler for elvis operator that + follows safe call operator is filtered out during generation of report + (GitHub #1814).
  • Fixed bugs

    From b97ebeb210592969624eefffa524fde6709b714f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 23:36:12 +0200 Subject: [PATCH 214/255] Upgrade Kotlin to 2.1.21 (#1886) --- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 609325879e..bda92a1a41 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.1.20 + 2.1.21 From c12c0ad69b1ba5b4fac4fd875b898e82c19543a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:59:12 +0200 Subject: [PATCH 215/255] Upgrade maven-clean-plugin to 3.5.0 (#1890) --- 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 67512a72ce..4258187767 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -307,7 +307,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.4.1 + 3.5.0 org.apache.maven.plugins From c23870b8c7553f2a4482129a07b8d050b566c86a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:28:27 +0000 Subject: [PATCH 216/255] Upgrade exec-maven-plugin to 3.5.1 (#1891) --- 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 4258187767..dda3337c08 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -434,7 +434,7 @@ org.codehaus.mojo exec-maven-plugin - 3.5.0 + 3.5.1 From c8977ecb87f1c81539a36902a919f18f019393c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 11:16:11 +0000 Subject: [PATCH 217/255] Upgrade spotless-maven-plugin to 2.44.5 (#1889) --- 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 dda3337c08..7435f7f470 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.44.4 + 2.44.5 org.sonarsource.scanner.maven From 582bcb783dcbfbc7c84e77b4b7d5ebc18b1f1044 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 11 Jun 2025 06:20:55 +0100 Subject: [PATCH 218/255] Migrate publishing of snapshot to the Central Publisher Portal (#1897) --- org.jacoco.build/pom.xml | 2 +- org.jacoco.doc/docroot/doc/repo.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 7435f7f470..44ab868993 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -125,7 +125,7 @@ UTF-8 - https://oss.sonatype.org/content/repositories/snapshots/ + https://central.sonatype.com/repository/maven-snapshots/ yyyyMMddhhmm http://www.jacoco.org/jacoco diff --git a/org.jacoco.doc/docroot/doc/repo.html b/org.jacoco.doc/docroot/doc/repo.html index be517de102..6b97158fb0 100644 --- a/org.jacoco.doc/docroot/doc/repo.html +++ b/org.jacoco.doc/docroot/doc/repo.html @@ -40,7 +40,7 @@

    Maven Repository

    Snapshot - https://oss.sonatype.org/content/repositories/snapshots + https://central.sonatype.com/repository/maven-snapshots/ From 8df6db981c3ead8918a799c9fd4547c17ea045cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 23:03:04 +0200 Subject: [PATCH 219/255] Upgrade build-helper-maven-plugin to 3.6.1 (#1900) --- 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 44ab868993..357629cb3d 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -419,7 +419,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.6.0 + 3.6.1 org.codehaus.mojo From fc3726eaa6bd48c342d2c0c41b62297d7be4928a Mon Sep 17 00:00:00 2001 From: "Marc R. Hoffmann" Date: Thu, 12 Jun 2025 01:23:40 +0200 Subject: [PATCH 220/255] Add experimental support for Java 26 (#1870) Co-authored-by: Marc R. Hoffmann Co-authored-by: Evgeny Mandrikov --- .azure-pipelines/azure-pipelines.yml | 2 ++ org.jacoco.build/pom.xml | 14 +++++++++ org.jacoco.core.test.validation/pom.xml | 31 +++++++++++++++++++ .../jacoco/core/analysis/AnalyzerTest.java | 10 +++--- .../core/instr/ClassFileVersionsTest.java | 8 ++++- .../jacoco/core/instr/InstrumenterTest.java | 8 ++--- .../core/internal/instr/InstrSupportTest.java | 15 ++++----- .../core/internal/instr/InstrSupport.java | 4 +-- org.jacoco.doc/docroot/doc/build.html | 11 +++++++ org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/docroot/doc/faq.html | 2 +- 11 files changed, 87 insertions(+), 20 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index 7193d8a017..f9ca32e443 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -56,6 +56,8 @@ jobs: JDK_VERSION: 24 JDK 25: JDK_VERSION: 25 + JDK 26: + JDK_VERSION: 26 pool: vmImage: 'ubuntu-24.04' steps: diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 357629cb3d..679c8ae850 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -961,6 +961,20 @@
    + + java26-bytecode + + + bytecode.version + 26 + + + + 17 + 17 + + + ecj diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 79beb591f3..0a7c5f1f83 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -585,6 +585,37 @@ + + java26-bytecode + + + bytecode.version + 26 + + + + + 23 + + 16 + + 26 + 26 + + + ../org.jacoco.core.test.validation.kotlin + ../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 0d86b7a5d0..5840b3b09d 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 @@ -111,7 +111,7 @@ public void should_ignore_synthetic_classes() throws Exception { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V23 + 1); + final byte[] originalBytes = createClass(Opcodes.V25 + 1); final byte[] bytes = new byte[originalBytes.length]; System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length); final long expectedClassId = CRC64.classId(bytes); @@ -134,13 +134,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.V24 + 2); + final byte[] bytes = createClass(Opcodes.V25 + 2); try { analyzer.analyzeClass(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 70", + assertEquals("Unsupported class file major version 71", e.getCause().getMessage()); } } @@ -220,14 +220,14 @@ public void testAnalyzeClass_BrokenStream() throws IOException { */ @Test public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() { - final byte[] bytes = createClass(Opcodes.V24 + 2); + final byte[] bytes = createClass(Opcodes.V25 + 2); try { analyzer.analyzeAll(new ByteArrayInputStream(bytes), "UnsupportedVersion"); fail("exception expected"); } catch (IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 70", + assertEquals("Unsupported class file major version 71", 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 9d73f3144a..a25805fe84 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 @@ -47,6 +47,7 @@ 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.V25; import static org.objectweb.asm.Opcodes.V9; import java.io.IOException; @@ -189,7 +190,12 @@ public void test_24() throws IOException { @Test public void test_25() throws IOException { - testVersion(V24 + 1, true); + testVersion(V25, true); + } + + @Test + public void test_26() throws IOException { + testVersion(V25 + 1, true); } private void testVersion(int version, boolean frames) throws IOException { 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 1050937333..ff53a5aed0 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.V24 + 2); + final byte[] bytes = createClass(Opcodes.V25 + 2); try { instrumenter.instrument(bytes, "UnsupportedVersion"); fail("exception expected"); } catch (final IOException e) { assertExceptionMessage("UnsupportedVersion", e); - assertEquals("Unsupported class file major version 70", + assertEquals("Unsupported class file major version 71", 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.V24 + 2); + final byte[] bytes = createClass(Opcodes.V25 + 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 70", + assertEquals("Unsupported class file major version 71", 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 5b144b5da6..9cdcb964bb 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_25_class() { - final byte[] bytes = createJava25Class(); + public void classReaderFor_should_read_java_26_class() { + final byte[] bytes = createJava26Class(); final ClassReader classReader = InstrSupport.classReaderFor(bytes); @@ -53,16 +53,16 @@ public void classReaderFor_should_read_java_25_class() { public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { - assertEquals(Opcodes.V24 + 1, version); + assertEquals(Opcodes.V25 + 1, version); } }, 0); - assertArrayEquals(createJava25Class(), bytes); + assertArrayEquals(createJava26Class(), bytes); } - private static byte[] createJava25Class() { + private static byte[] createJava26Class() { final ClassWriter cw = new ClassWriter(0); - cw.visit(Opcodes.V24 + 1, 0, "Foo", null, "java/lang/Object", null); + cw.visit(Opcodes.V25 + 1, 0, "Foo", null, "java/lang/Object", null); cw.visitEnd(); return cw.toByteArray(); } @@ -136,7 +136,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_ assertTrue(InstrSupport.needsFrames(Opcodes.V22)); assertTrue(InstrSupport.needsFrames(Opcodes.V23)); assertTrue(InstrSupport.needsFrames(Opcodes.V24)); - assertTrue(InstrSupport.needsFrames(Opcodes.V24 + 1)); + assertTrue(InstrSupport.needsFrames(Opcodes.V25)); + assertTrue(InstrSupport.needsFrames(Opcodes.V25 + 1)); assertTrue(InstrSupport.needsFrames(0x0100)); } 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 9883453c3d..62267e6e86 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.V24 + 1) { + if (originalVersion == Opcodes.V25 + 1) { // temporarily downgrade version to bypass check in ASM - setMajorVersion(Opcodes.V24, b); + setMajorVersion(Opcodes.V25, b); } final ClassReader classReader = new ClassReader(b); setMajorVersion(originalVersion, b); diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html index 7a64b9cbfa..d34b18d77a 100644 --- a/org.jacoco.doc/docroot/doc/build.html +++ b/org.jacoco.doc/docroot/doc/build.html @@ -102,6 +102,7 @@

    Compilation and testing with different JDKs

    JDK 23 JDK 24 JDK 25 + JDK 26 @@ -128,6 +129,7 @@

    Compilation and testing with different JDKs

    21 21 21 + 21 org.jacoco.core.test.validation.java16 @@ -152,6 +154,7 @@

    Compilation and testing with different JDKs

    16 16 16 + 16 org.jacoco.core.test.validation.java14 @@ -176,6 +179,7 @@

    Compilation and testing with different JDKs

    14 14 14 + 14 org.jacoco.core.test.validation.java8 @@ -200,6 +204,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 org.jacoco.core.test.validation.java7 @@ -224,6 +229,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 org.jacoco.core.test.validation.groovy @@ -248,6 +254,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 org.jacoco.core.test.validation.kotlin @@ -272,6 +279,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 org.jacoco.core.test.validation.scala @@ -296,6 +304,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 all other modules @@ -320,6 +329,7 @@

    Compilation and testing with different JDKs

    8 8 8 + 8 @@ -375,6 +385,7 @@

    Compilation and testing with different JDKs

  • ../mvnw clean verify -Djdk.version=23 -Dbytecode.version=23
  • ../mvnw clean verify -Djdk.version=24 -Dbytecode.version=24
  • ../mvnw clean verify -Djdk.version=25 -Dbytecode.version=25
  • +
  • ../mvnw clean verify -Djdk.version=26 -Dbytecode.version=26
  • diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index a1fd430b3c..56db2bb3f4 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,6 +22,8 @@

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    New Features

      +
    • Experimental support for Java 26 class files + (GitHub #1870).
    • Branches added by the Kotlin compiler for default argument number 33 or higher are filtered out during generation of report (GitHub #1655).
    • diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html index afa6d507c7..537e7592be 100644 --- a/org.jacoco.doc/docroot/doc/faq.html +++ b/org.jacoco.doc/docroot/doc/faq.html @@ -46,7 +46,7 @@

      Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?

      What Java versions are supported by JaCoCo?

      JaCoCo officially supports Java class files from version 1.0 to 24. Also - experimental support for class files of version 25 is provided. + experimental support for class files of version 25 and 26 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. From e6861dd52e2e1c9723654fdb99bc067d2a89768c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 10:11:35 +0200 Subject: [PATCH 221/255] Upgrade maven-invoker-plugin to 3.9.1 (#1907) --- 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 679c8ae850..ac605cd5ff 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -338,7 +338,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.9.0 + 3.9.1 org.apache.maven.plugins From 2b5ab9a2ca11ad3327cac60657254370a8351c29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:00:28 +0200 Subject: [PATCH 222/255] Upgrade maven-gpg-plugin to 3.2.8 (#1910) --- 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 ac605cd5ff..e60fb39732 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -343,7 +343,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.7 + 3.2.8 org.apache.maven.plugins From 4f6a51b7814730f7bbf5c27c359dc19505ab2758 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 16:04:49 +0200 Subject: [PATCH 223/255] Upgrade maven-enforcer-plugin to 3.6.0 (#1909) --- 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 e60fb39732..65a8449ecd 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -328,7 +328,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.5.0 + 3.6.0 org.apache.maven.plugins From a4cee188c95d56f19725144720c1f79004d80527 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 11:43:18 +0200 Subject: [PATCH 224/255] Upgrade spotless-maven-plugin to 2.45.0 (#1917) --- 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 65a8449ecd..62052b26db 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.44.5 + 2.45.0 org.sonarsource.scanner.maven From 97e7f62046c4cdb6c1b365b087974cd8688166dd Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:05:09 +0300 Subject: [PATCH 225/255] Upgrade Maven to 3.9.11 (#1912) --- .mvn/wrapper/maven-wrapper.properties | 4 ++-- org.jacoco.build/pom.xml | 2 +- org.jacoco.doc/docroot/doc/environment.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index fe9deed0b0..546a64e725 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -16,5 +16,5 @@ # under the License. wrapperVersion=3.3.2 distributionType=only-script -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip -distributionSha256Sum=4ec3f26fb1a692473aea0235c300bd20f0f9fe741947c82c1234cefd76ac3a3c +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip +distributionSha256Sum=0d7125e8c91097b36edb990ea5934e6c68b4440eef4ea96510a0f6815e7eeadb diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 62052b26db..a0d561f0b6 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -520,7 +520,7 @@ 17 - 3.9.9 + 3.9.11 The rules for repo1.maven.org are that pom.xml files should not include repository definitions. diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html index f56639a9bc..838c209b9a 100644 --- a/org.jacoco.doc/docroot/doc/environment.html +++ b/org.jacoco.doc/docroot/doc/environment.html @@ -76,7 +76,7 @@

      Build

      The JaCoCo build is based on Maven - and requires at least Maven 3.9.9 and JDK 17. + and requires at least Maven 3.9.11 and JDK 17. See the build description for details.

      From 5fda1315076acc29a22589921002f7890930f732 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:23:58 +0200 Subject: [PATCH 226/255] Upgrade maven-enforcer-plugin to 3.6.1 (#1927) --- 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 a0d561f0b6..4a452c6420 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -328,7 +328,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.6.0 + 3.6.1 org.apache.maven.plugins From ec92eda4c3b84a7cd21a02b1d78691111ea4c294 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 7 Aug 2025 01:22:25 +0200 Subject: [PATCH 227/255] KotlinCoroutineFilter should filter inlined invocations of `suspendCoroutineUninterceptedOrReturn` (#1929) --- .../kotlin/KotlinCoroutineCallbackTest.java | 27 ++++++ .../targets/KotlinCoroutineCallbackTarget.kt | 49 +++++++++++ .../filter/KotlinCoroutineFilterTest.java | 83 +++++++++++++++++++ .../filter/KotlinCoroutineFilter.java | 35 ++++++++ org.jacoco.doc/docroot/doc/changes.html | 4 + 5 files changed, 198 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineCallbackTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineCallbackTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineCallbackTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineCallbackTest.java new file mode 100644 index 0000000000..d779f14b44 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineCallbackTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinCoroutineCallbackTarget; + +/** + * Test of code coverage in {@link KotlinCoroutineCallbackTarget}. + */ +public class KotlinCoroutineCallbackTest extends ValidationTestBase { + + public KotlinCoroutineCallbackTest() { + super(KotlinCoroutineCallbackTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineCallbackTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineCallbackTarget.kt new file mode 100644 index 0000000000..5ec8d243b7 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineCallbackTarget.kt @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.coroutines.runBlocking +import org.jacoco.core.test.validation.targets.Stubs.nop +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +/** + * Test target containing invocations of [kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn] intrinsic + * inlined from [suspendCoroutine] which provides a way to + * [wrap any callback into a Kotlin suspending function](https://github.com/Kotlin/KEEP/blob/main/proposals/KEEP-0164-coroutines.md#wrapping-callbacks). + * + * @see [kotlinx.coroutines.suspendCancellableCoroutine] + */ +object KotlinCoroutineCallbackTarget { + + suspend fun example() = + suspendCoroutine { continuation -> // assertFullyCovered() + continuation.resume(Unit) // assertFullyCovered() + } // assertFullyCovered() + + suspend fun withoutTailCallOptimization() { + suspendCoroutine { continuation -> // assertFullyCovered() + continuation.resume(Unit) // assertFullyCovered() + } // assertFullyCovered() + nop("tail") // assertFullyCovered() + } + + @JvmStatic + fun main(args: Array) { + runBlocking { + example() + withoutTailCallOptimization() + } + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java index ab906df8f4..2054181367 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java @@ -511,4 +511,87 @@ public void should_filter_Kotlin_1_6_suspending_lambda_without_suspension_points assertIgnored(m, range0, range1); } + /** + *
      +	 *     suspend fun example() =
      +	 *         suspendCoroutine { continuation ->
      +	 *             ...
      +	 *         }
      +	 * 
      + * + * @see #should_filter_suspendCoroutineUninterceptedOrReturn_when_no_tail_call_optimization() + */ + @Test + public void should_filter_suspendCoroutineUninterceptedOrReturn() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "example", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, + null); + + m.visitInsn(Opcodes.NOP); + + m.visitInsn(Opcodes.DUP); + final Range range0 = new Range(); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, label); + range0.fromInclusive = m.instructions.getLast(); + m.visitInsn(Opcodes.ALOAD); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/jvm/internal/DebugProbesKt", + "probeCoroutineSuspended", + "(Lkotlin/coroutines/Continuation;)V", false); + range0.toInclusive = m.instructions.getLast(); + m.visitLabel(label); + + filter.filter(m, context, output); + + assertIgnored(m, range0); + } + + /** + *
      +	 *     suspend fun example() {
      +	 *         suspendCoroutine { continuation ->
      +	 *             ...
      +	 *         }
      +	 *         ...
      +	 *     }
      +	 * 
      + * + * @see #should_filter_suspendCoroutineUninterceptedOrReturn() + */ + @Test + public void should_filter_suspendCoroutineUninterceptedOrReturn_when_no_tail_call_optimization() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "example", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, + null); + + m.visitInsn(Opcodes.NOP); + + m.visitInsn(Opcodes.DUP); + final Range range0 = new Range(); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, label); + range0.fromInclusive = m.instructions.getLast(); + m.visitInsn(Opcodes.ALOAD); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/coroutines/Continuation"); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/jvm/internal/DebugProbesKt", + "probeCoroutineSuspended", + "(Lkotlin/coroutines/Continuation;)V", false); + range0.toInclusive = m.instructions.getLast(); + m.visitLabel(label); + + filter.filter(m, context, output); + + assertIgnored(m, range0); + } + } 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 307710f1a6..40a9b8c829 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 @@ -32,9 +32,44 @@ public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { new Matcher().match(methodNode, output); new Matcher().matchOptimizedTailCall(methodNode, output); + new Matcher().matchSuspendCoroutineUninterceptedOrReturn(methodNode, + output); } private static class Matcher extends AbstractMatcher { + /** + * Filters + * bytecode generated for inlined invocations of + * kotlin.coroutines.intrinsics/suspendCoroutineUninterceptedOrReturn + */ + private void matchSuspendCoroutineUninterceptedOrReturn( + final MethodNode methodNode, final IFilterOutput output) { + for (final AbstractInsnNode i : methodNode.instructions) { + cursor = i; + nextIs(Opcodes.DUP); + nextIsInvoke(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;"); + nextIs(Opcodes.IF_ACMPNE); + final JumpInsnNode jumpInstruction = (JumpInsnNode) cursor; + nextIs(Opcodes.ALOAD); + if (cursor != null + && cursor.getNext().getOpcode() == Opcodes.CHECKCAST) { + nextIsType(Opcodes.CHECKCAST, + "kotlin/coroutines/Continuation"); + } + nextIsInvoke(Opcodes.INVOKESTATIC, + "kotlin/coroutines/jvm/internal/DebugProbesKt", + "probeCoroutineSuspended", + "(Lkotlin/coroutines/Continuation;)V"); + if (cursor != null + && jumpInstruction.label == cursor.getNext()) { + output.ignore(jumpInstruction, cursor); + } + } + } private void matchOptimizedTailCall(final MethodNode methodNode, final IFilterOutput output) { diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 56db2bb3f4..03b5876a82 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -30,6 +30,10 @@

      New Features

    • Part of bytecode generated by the Kotlin compiler for elvis operator that follows safe call operator is filtered out during generation of report (GitHub #1814).
    • +
    • Part of bytecode generated by the Kotlin compiler for invocations of + suspendCoroutineUninterceptedOrReturn intrinsic is filtered out + during generation of report + (GitHub #1929).

    Fixed bugs

    From 562a7299399b8321dfcf8eeb21ea4bfc27556fdc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 23:28:06 +0200 Subject: [PATCH 228/255] Upgrade spotless-maven-plugin to 2.46.1 (#1926) --- 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 4a452c6420..d99e1380ac 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.45.0 + 2.46.1 org.sonarsource.scanner.maven From 8f24208e22d87e34345c49f19b23d813f45a1815 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Aug 2025 21:48:41 +0200 Subject: [PATCH 229/255] Bump actions/checkout from 4.2.2 to 5.0.0 (#1932) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [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/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... 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 240ea5a4a9..126e846752 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-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'zulu' @@ -58,7 +58,7 @@ jobs: Windows: runs-on: windows-2022 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'zulu' From f891f36f6d522f0e50ab4c46c7f36a7bbeacfacb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:20:07 +0200 Subject: [PATCH 230/255] Bump actions/setup-java from 4.7.1 to 5.0.0 (#1941) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/c5195efecf7bdfc987ee8bae7a71cb8b11521c00...dded0888837ed1f317902acf8a20df0ad188d165) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... 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 126e846752..56de7f2ce4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'zulu' java-version: | @@ -59,7 +59,7 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'zulu' java-version: | From 959b0989a76678fad530665bfe13f5a8d1cdae05 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 27 Aug 2025 19:34:51 +0200 Subject: [PATCH 231/255] Fix KotlinWhenStringFilter and StringSwitchFilter (#1940) --- .../java7/targets/StringSwitchTarget.java | 18 ++++++++++ .../kotlin/targets/KotlinWhenStringTarget.kt | 12 +++++++ .../analysis/filter/FilterTestBase.java | 35 ++++++------------- .../filter/KotlinWhenStringFilterTest.java | 10 +++--- .../filter/StringSwitchFilterTest.java | 22 ++++++------ .../core/test/validation/targets/Stubs.java | 7 ++++ .../filter/KotlinWhenStringFilter.java | 2 +- .../analysis/filter/Replacements.java | 2 +- .../analysis/filter/StringSwitchFilter.java | 2 +- org.jacoco.doc/docroot/doc/changes.html | 6 ++-- 10 files changed, 71 insertions(+), 45 deletions(-) diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java index 575f370784..127e20b1ac 100644 --- a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java +++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java @@ -14,6 +14,8 @@ import static org.jacoco.core.test.validation.targets.Stubs.nop; +import org.jacoco.core.test.validation.targets.Stubs; + /** * This test target is a switch statement with a String. */ @@ -36,6 +38,20 @@ private static void covered(Object s) { } } + private static void executedWithSameHashCodeAsFirstCase() { + switch (Stubs.string("\0a")) { // assertFullyCovered(2, 1) + case "a": + nop("case a"); // assertNotCovered() + break; + case "b": + nop("case b"); // assertNotCovered() + break; + default: + nop("default"); // assertFullyCovered() + break; + } + } + private static void notCovered(Object s) { switch (String.valueOf(s)) { // assertNotCovered(4, 0) case "a": @@ -133,6 +149,8 @@ public static void main(String[] args) { covered("b"); covered("\0a"); + executedWithSameHashCodeAsFirstCase(); + implicitDefaultNotExecuted("a"); implicitDefaultNotExecuted("b"); implicitDefaultNotExecuted("c"); 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 index 2ff0c227c3..9aec8a767a 100644 --- 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 @@ -13,6 +13,7 @@ package org.jacoco.core.test.validation.kotlin.targets import org.jacoco.core.test.validation.targets.Stubs.nop +import org.jacoco.core.test.validation.targets.Stubs.string /** * Test target with `when` expressions and statements with subject of type `String`. @@ -57,6 +58,15 @@ object KotlinWhenStringTarget { } // assertEmpty() } // assertFullyCovered() + private fun executedWithSameHashCodeAsFirstCase() { + when (string("\u0000a")) { // assertFullyCovered(3, 1) + "a" -> nop("case a") // assertNotCovered() + "b" -> nop("case b") // assertNotCovered() + "c" -> nop("case c") // assertNotCovered() + else -> nop("else") // assertFullyCovered() + } // assertEmpty() + } // assertFullyCovered() + /** * Unlike [whenString] * in this example first case is the only case with biggest hashCode value. @@ -96,6 +106,8 @@ object KotlinWhenStringTarget { implicitElseNotExecuted("b") implicitElseNotExecuted("c") + executedWithSameHashCodeAsFirstCase() + whenStringBiggestHashCodeFirst("") whenStringBiggestHashCodeFirst("a") whenStringBiggestHashCodeFirst("b") 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 3a2d7ce4ea..bc3cc215b2 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 @@ -111,41 +111,28 @@ final void assertReplacedBranches(final MethodNode methodNode, private void assertReplacements(final MethodNode methodNode, final AbstractInsnNode source, final List expectedReplacements) { - - Collections.sort(expectedReplacements, new Comparator() { - public int compare(final Replacement r1, final Replacement r2) { - if (r1.newBranch == r2.newBranch) { - return r1.branch - r2.branch; - } - return r1.newBranch - r2.newBranch; - } - }); - - final StringBuilder expectedStringBuilder = new StringBuilder(); + final ArrayList expectedStrings = new ArrayList(); for (final Replacement replacement : expectedReplacements) { - expectedStringBuilder.append(replacement.newBranch) - .append(" if branch ").append(replacement.branch) - .append(" of instruction ").append(methodNode.instructions - .indexOf(replacement.instruction)) - .append("\n"); + expectedStrings.add("\n" + replacement.newBranch + " if branch " + + replacement.branch + " of instruction " + + methodNode.instructions.indexOf(replacement.instruction)); } + Collections.sort(expectedStrings); - final StringBuilder actualStringBuilder = new StringBuilder(); + final ArrayList actualStrings = new ArrayList(); int newBranch = 0; for (final Collection pairs : actualReplacements .get(source)) { for (Replacements.InstructionBranch pair : pairs) { - actualStringBuilder.append(newBranch).append(" if branch ") - .append(pair.branch).append(" of instruction ") - .append(methodNode.instructions - .indexOf(pair.instruction)) - .append("\n"); + actualStrings.add("\n" + newBranch + " if branch " + pair.branch + + " of instruction " + + methodNode.instructions.indexOf(pair.instruction)); } newBranch++; } + Collections.sort(actualStrings); - assertEquals(expectedStringBuilder.toString(), - actualStringBuilder.toString()); + assertEquals(expectedStrings.toString(), actualStrings.toString()); } static class Replacement { diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java index b1d0ef027a..c9b5b707b2 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java @@ -66,7 +66,7 @@ public void should_filter() { "(Ljava/lang/Object;)Z", false); m.visitJumpInsn(Opcodes.IFEQ, sameHash); m.visitJumpInsn(Opcodes.GOTO, case1); - replacements.add(new Replacement(1, m.instructions.getLast(), 0)); + replacements.add(new Replacement(1, m.instructions.getLast(), 1)); // case "\u0000a" m.visitLabel(sameHash); @@ -77,7 +77,7 @@ public void should_filter() { m.visitJumpInsn(Opcodes.IFEQ, defaultCase); replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, case2); - replacements.add(new Replacement(2, m.instructions.getLast(), 0)); + replacements.add(new Replacement(2, m.instructions.getLast(), 1)); // case "b" m.visitLabel(h2); @@ -89,7 +89,7 @@ public void should_filter() { replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, case3); final AbstractInsnNode expectedToInclusive = m.instructions.getLast(); - replacements.add(new Replacement(3, m.instructions.getLast(), 0)); + replacements.add(new Replacement(3, m.instructions.getLast(), 1)); m.visitLabel(case1); m.visitInsn(Opcodes.RETURN); @@ -145,7 +145,7 @@ public void should_filter_when_biggest_hashCode_first() { "(Ljava/lang/Object;)Z", false); m.visitJumpInsn(Opcodes.IFEQ, sameHash); m.visitJumpInsn(Opcodes.GOTO, case2); - replacements.add(new Replacement(1, m.instructions.getLast(), 0)); + replacements.add(new Replacement(1, m.instructions.getLast(), 1)); m.visitLabel(sameHash); m.visitVarInsn(Opcodes.ALOAD, 2); @@ -155,7 +155,7 @@ public void should_filter_when_biggest_hashCode_first() { m.visitJumpInsn(Opcodes.IFEQ, defaultCase); replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, case3); - replacements.add(new Replacement(2, m.instructions.getLast(), 0)); + replacements.add(new Replacement(2, m.instructions.getLast(), 1)); m.visitLabel(h2); m.visitVarInsn(Opcodes.ALOAD, 2); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java index 53e633b0c6..6ea3981d7e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchFilterTest.java @@ -76,7 +76,7 @@ public void should_filter() { // goto default case m.visitJumpInsn(Opcodes.GOTO, caseDefault); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(h2); @@ -91,7 +91,7 @@ public void should_filter() { // goto default case m.visitJumpInsn(Opcodes.GOTO, caseDefault); range.toInclusive = m.instructions.getLast(); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(case1); m.visitInsn(Opcodes.RETURN); @@ -212,7 +212,7 @@ public void should_filter_Kotlin_1_5() { replacements.add(new Replacement(2, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, defaultCase); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(h2); m.visitVarInsn(Opcodes.ALOAD, 1); @@ -230,7 +230,7 @@ public void should_filter_Kotlin_1_5() { replacements.add(new Replacement(4, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, defaultCase); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(h3); m.visitVarInsn(Opcodes.ALOAD, 1); @@ -249,7 +249,7 @@ public void should_filter_Kotlin_1_5() { m.visitJumpInsn(Opcodes.GOTO, defaultCase); range.toInclusive = m.instructions.getLast(); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(case1); m.visitInsn(Opcodes.RETURN); @@ -319,7 +319,7 @@ public void should_filter_Kotlin_nullable_else() { m.visitJumpInsn(Opcodes.IFNE, caseA); replacements.add(new Replacement(1, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(hashB); m.visitVarInsn(Opcodes.ALOAD, 2); @@ -329,7 +329,7 @@ public void should_filter_Kotlin_nullable_else() { m.visitJumpInsn(Opcodes.IFNE, caseB); replacements.add(new Replacement(2, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(hashC); m.visitVarInsn(Opcodes.ALOAD, 2); @@ -340,7 +340,7 @@ public void should_filter_Kotlin_nullable_else() { replacements.add(new Replacement(3, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); range.toInclusive = m.instructions.getLast(); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(caseA); m.visitLdcInsn("case a"); @@ -415,7 +415,7 @@ public void should_filter_Kotlin_nullable_case() { m.visitJumpInsn(Opcodes.IFNE, caseA); replacements.add(new Replacement(1, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(hashB); m.visitVarInsn(Opcodes.ALOAD, 2); @@ -425,7 +425,7 @@ public void should_filter_Kotlin_nullable_case() { m.visitJumpInsn(Opcodes.IFNE, caseB); replacements.add(new Replacement(2, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(hashC); m.visitVarInsn(Opcodes.ALOAD, 2); @@ -436,7 +436,7 @@ public void should_filter_Kotlin_nullable_case() { replacements.add(new Replacement(3, m.instructions.getLast(), 1)); m.visitJumpInsn(Opcodes.GOTO, caseElse); range.toInclusive = m.instructions.getLast(); - replacements.add(new Replacement(0, m.instructions.getLast(), 0)); + replacements.add(new Replacement(0, m.instructions.getLast(), 1)); m.visitLabel(caseA); m.visitLdcInsn("case a"); diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java index 3912639b84..1768557dc9 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java +++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java @@ -119,6 +119,13 @@ public static Enum enumA() { return Enum.A; } + /** + * @return given argument + */ + public static String string(final String value) { + return value; + } + /** * Always throws a {@link RuntimeException}. * 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 2296948335..90b3b88012 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 @@ -86,7 +86,7 @@ public void match(final AbstractInsnNode start, } else if (cursor.getOpcode() == Opcodes.GOTO) { // jump to case body replacements.add(((JumpInsnNode) cursor).label, cursor, - 0); + 1); if (jump.label == defaultLabel) { // end of comparisons for same hashCode replacements.add(defaultLabel, jump, 1); diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java index 0a7a03c386..1e3cb00707 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Replacements.java @@ -56,7 +56,7 @@ public final class Replacements { * * *
  • for {@link org.objectweb.asm.tree.JumpInsnNode} with - * {@link org.objectweb.asm.Opcodes#GOTO} there is only branch 0 that + * {@link org.objectweb.asm.Opcodes#GOTO} there is only branch 1 that * corresponds to continuation of execution at * {@link org.objectweb.asm.tree.JumpInsnNode#label}
  • * 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 17d62a802c..3d8b041c7b 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 @@ -107,7 +107,7 @@ public void match(final AbstractInsnNode start, // end of comparisons for same hashCode // jump to default nextIs(Opcodes.GOTO); - replacements.add(defaultLabel, cursor, 0); + replacements.add(defaultLabel, cursor, 1); break; } else if (cursor.getNext() == defaultLabel) { replacements.add(defaultLabel, cursor, 0); diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 03b5876a82..d3855a7255 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -40,10 +40,12 @@

    Fixed bugs

    • Fixed handling of implicit else clause of when with String subject in Kotlin - (GitHub #1813).
    • + (GitHub #1813, + #1940).
    • Fixed handling of implicit default clause of switch by String in Java when compiled by ECJ - (GitHub #1813).
    • + (GitHub #1813, + #1940).
    • Fixed handling of exceptions in chains of safe call operators in Kotlin (GitHub #1819).
    From be39d2f5c4c62d9f69d92fcc5ecd99a5d32db195 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 31 Aug 2025 09:27:21 +0200 Subject: [PATCH 232/255] Fix KotlinCrossinlineTest (#1942) --- .../kotlin/KotlinCrossinlineTest.java | 11 +++++++++++ .../kotlin/targets/KotlinCrossinlineTarget.kt | 8 ++++++-- .../test/validation/ValidationTestBase.java | 18 +++++++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) 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 index 8d0258eca6..df788970de 100644 --- 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 @@ -12,6 +12,9 @@ *******************************************************************************/ package org.jacoco.core.test.validation.kotlin; +import java.util.Arrays; +import java.util.Collection; + import org.jacoco.core.test.validation.ValidationTestBase; import org.jacoco.core.test.validation.kotlin.targets.KotlinCrossinlineTarget; @@ -24,4 +27,12 @@ public KotlinCrossinlineTest() { super(KotlinCrossinlineTarget.class); } + @Override + protected Collection additionalClassesForAnalysis() { + // Analyze SMAPs in non executed classes: + return Arrays.asList( + "org.jacoco.core.test.validation.kotlin.targets.KotlinCrossinlineTarget$example$1", + "org.jacoco.core.test.validation.kotlin.targets.KotlinCrossinlineTarget$example$1$1"); + } + } 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 index fdd8cc18f9..ea538874cb 100644 --- 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 @@ -21,8 +21,12 @@ object KotlinCrossinlineTarget { inline fun example(crossinline lambda: () -> Unit): () -> Unit { // assertEmpty() return { // assertFullyCovered() - requireCrossinline { lambda() } // assertFullyCovered() - } // assertFullyCovered() + /* TODO next two lines are partly covered due to regression in Kotlin compiler version 2.0 + https://github.com/jacoco/jacoco/issues/1840 + https://youtrack.jetbrains.com/issue/KT-74617/Trivial-SMAP-optimization-leads-to-missing-debug-info-after-inline + */ + requireCrossinline { lambda() } // assertPartlyCovered() + } // assertPartlyCovered() } // assertEmpty() fun requireCrossinline(lambda: () -> Unit) = lambda() 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 5dfc21bbc2..5d24496b50 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 @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import org.jacoco.core.analysis.Analyzer; @@ -96,23 +97,30 @@ protected void run(final Class targetClass) throws Exception { (Object) new String[0]); } + protected Collection additionalClassesForAnalysis() { + return Collections.emptyList(); + } + private void analyze(final ExecutionDataStore store) throws IOException { final CoverageBuilder builder = new CoverageBuilder(); final Analyzer analyzer = new Analyzer(store, builder); for (ExecutionData data : store.getContents()) { - analyze(analyzer, data); + analyze(analyzer, data.getName()); + } + for (String className : additionalClassesForAnalysis()) { + analyze(analyzer, className); } final String testClassSimpleName = getClass().getSimpleName(); bundle = builder.getBundle(testClassSimpleName); source = Source.load(target, bundle); } - private void analyze(final Analyzer analyzer, final ExecutionData data) + private void analyze(final Analyzer analyzer, final String className) throws IOException { final byte[] bytes = TargetLoader - .getClassDataAsBytes(target.getClassLoader(), data.getName()); - analyzer.analyzeClass(bytes, data.getName()); - saveBytecodeRepresentations(bytes, data.getName()); + .getClassDataAsBytes(target.getClassLoader(), className); + analyzer.analyzeClass(bytes, className); + saveBytecodeRepresentations(bytes, className); } private void saveBytecodeRepresentations(final byte[] classBytes, From 24ba65feb8dbd3c1dae346ffbd11fa173232211a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 08:39:08 +0000 Subject: [PATCH 233/255] Upgrade Kotlin to 2.2.10 (#1935) 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 | 9 ++++++++- .../validation/kotlin/targets/KotlinCrossinlineTarget.kt | 8 ++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index bda92a1a41..5311e1496e 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.1.21 + 2.2.10 @@ -58,6 +58,13 @@ compile + + + + -jvm-default + disable + +
    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 index ea538874cb..fdd8cc18f9 100644 --- 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 @@ -21,12 +21,8 @@ object KotlinCrossinlineTarget { inline fun example(crossinline lambda: () -> Unit): () -> Unit { // assertEmpty() return { // assertFullyCovered() - /* TODO next two lines are partly covered due to regression in Kotlin compiler version 2.0 - https://github.com/jacoco/jacoco/issues/1840 - https://youtrack.jetbrains.com/issue/KT-74617/Trivial-SMAP-optimization-leads-to-missing-debug-info-after-inline - */ - requireCrossinline { lambda() } // assertPartlyCovered() - } // assertPartlyCovered() + requireCrossinline { lambda() } // assertFullyCovered() + } // assertFullyCovered() } // assertEmpty() fun requireCrossinline(lambda: () -> Unit) = lambda() From 1c1913f852d2435c233190f59484235d1a8d8e09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:18:23 +0200 Subject: [PATCH 234/255] Upgrade sonar-maven-plugin to 5.2.0.4988 (#1943) --- 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 d99e1380ac..c964fb2797 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -455,7 +455,7 @@ org.sonarsource.scanner.maven sonar-maven-plugin - 5.1.0.4751 + 5.2.0.4988 From 35988ed7670046a544819f421bf0a38bd49e64d9 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 1 Sep 2025 21:16:19 +0200 Subject: [PATCH 235/255] KotlinComposeFilter should filter bytecode generated for pausable composition (#1911) --- .../filter/KotlinComposeFilterTest.java | 103 ++++++++++++++++++ .../analysis/filter/KotlinComposeFilter.java | 7 ++ org.jacoco.doc/docroot/doc/changes.html | 3 + 3 files changed, 113 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java index 7df4b8bcfd..36257b20af 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinComposeFilterTest.java @@ -253,4 +253,107 @@ public void should_filter() { range7); } + /** + *
    +	 * @androidx.compose.runtime.Composable
    +	 * fun example() {
    +	 *   ... // body
    +	 * }
    +	 * 
    + * + * after + * change in Compose Kotlin compiler plugin version 2.1.0 transformed + * into + * + *
    +	 * fun example($composer: Composer?, $changed: Int) {
    +	 *   $composer = $composer.startRestartGroup(...)
    +	 *   sourceInformation($composer, ...)
    +	 *   if ($composer.shouldExecute(...)) {
    +	 *     ... // body
    +	 *   } else {
    +	 *     $composer.skipToGroupEnd()
    +	 *   }
    +	 *   $composer.endRestartGroup()?.updateScope { ... }
    +	 * }
    +	 * 
    + * + * This became + * the default in Compose Kotlin compiler plugin version 2.2.0 + */ + @Test + public void should_filter_pausable_composition() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "(Landroidx/compose/runtime/Composer;I)V", null, + null); + m.visitAnnotation("Landroidx/compose/runtime/Composable;", false); + + final Range range1 = new Range(); + final Range range2 = new Range(); + + m.visitVarInsn(ALOAD, 0); + range1.fromInclusive = m.instructions.getLast(); + m.visitLdcInsn(Integer.valueOf(-933543558)); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "startRestartGroup", "(I)Landroidx/compose/runtime/Composer;", + true); + m.visitVarInsn(ASTORE, 0); + m.visitVarInsn(ALOAD, 0); + m.visitVarInsn(ILOAD, 1); + final Label label1 = new Label(); + m.visitJumpInsn(IFEQ, label1); + m.visitInsn(ICONST_1); + final Label label2 = new Label(); + m.visitJumpInsn(GOTO, label2); + m.visitLabel(label1); + m.visitInsn(ICONST_0); + m.visitLabel(label2); + m.visitVarInsn(ILOAD, 1); + m.visitInsn(ICONST_1); + m.visitInsn(IAND); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "shouldExecute", "(ZI)Z", true); + final Label label3 = new Label(); + m.visitJumpInsn(IFEQ, label3); + range1.toInclusive = m.instructions.getLast(); + + // body + final Label label5 = new Label(); + m.visitJumpInsn(GOTO, label5); + + m.visitLabel(label3); + m.visitVarInsn(ALOAD, 0); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "skipToGroupEnd", "()V", true); + m.visitLabel(label5); + m.visitVarInsn(ALOAD, 0); + m.visitMethodInsn(INVOKEINTERFACE, "androidx/compose/runtime/Composer", + "endRestartGroup", + "()Landroidx/compose/runtime/ScopeUpdateScope;", true); + m.visitInsn(DUP); + final Label label6 = new Label(); + m.visitJumpInsn(IFNULL, label6); + range2.fromInclusive = m.instructions.getLast(); + m.visitVarInsn(ILOAD, 1); + m.visitInvokeDynamicInsn("invoke", + "(I)Lkotlin/jvm/functions/Function2;", null); + m.visitMethodInsn(INVOKEINTERFACE, + "androidx/compose/runtime/ScopeUpdateScope", "updateScope", + "(Lkotlin/jvm/functions/Function2;)V", true); + final Label label7 = new Label(); + m.visitJumpInsn(GOTO, label7); + m.visitLabel(label6); + m.visitInsn(POP); + range2.toInclusive = m.instructions.getLast(); + + m.visitLabel(label7); + m.visitInsn(RETURN); + + filter.filter(m, context, output); + + assertIgnored(m, range1, range2); + } + } 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 f3c01d96df..bbb25b2cb5 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 @@ -35,6 +35,13 @@ public void filter(final MethodNode methodNode, } final MethodInsnNode mi = (MethodInsnNode) i; if ("androidx/compose/runtime/Composer".equals(mi.owner) + && "shouldExecute".equals(mi.name) + && "(ZI)Z".equals(mi.desc) + && mi.getNext().getOpcode() == Opcodes.IFEQ) { + // https://github.com/JetBrains/kotlin/commit/ee9217f8f0f37967684fbfe4a568c2b3c8707507 + final JumpInsnNode ji = (JumpInsnNode) mi.getNext(); + output.ignore(methodNode.instructions.getFirst(), ji); + } else if ("androidx/compose/runtime/Composer".equals(mi.owner) && "getSkipping".equals(mi.name) && "()Z".equals(mi.desc) && mi.getNext().getOpcode() == Opcodes.IFNE) { // https://github.com/JetBrains/kotlin/blob/v2.0.0-RC2/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt#L361-L384 diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index d3855a7255..13941a8c61 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -34,6 +34,9 @@

    New Features

    suspendCoroutineUninterceptedOrReturn intrinsic is filtered out during generation of report (GitHub #1929). +
  • Part of bytecode generated by the Kotlin Compose compiler plugin for pausable + composition is filtered out during generation of report + (GitHub #1911).
  • Fixed bugs

    From deae0ad1f541990ea077023abdcacdc06a7e9184 Mon Sep 17 00:00:00 2001 From: Sander Jochems Date: Wed, 10 Sep 2025 00:15:28 +0200 Subject: [PATCH 236/255] Bump org.apache.maven.shared:file-management from 3.1.0 to 3.2.0 (#1947) --- jacoco-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index 61940a50a3..9345168453 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -59,7 +59,7 @@ org.apache.maven.shared file-management - 3.1.0 + 3.2.0 From 0d2405a78df6a07ee8da2bae6b8a910d2840c934 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 14 Sep 2025 22:44:57 +0000 Subject: [PATCH 237/255] Upgrade Kotlin to 2.2.20 (#1948) 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 +- .../test/validation/kotlin/targets/KotlinJvmOverloadsTarget.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 5311e1496e..6195ad4005 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.2.10 + 2.2.20 diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmOverloadsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmOverloadsTarget.kt index 408be57452..749ad7099a 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmOverloadsTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinJvmOverloadsTarget.kt @@ -19,7 +19,7 @@ import org.jacoco.core.test.validation.targets.Stubs.nop */ object KotlinJvmOverloadsTarget { - @JvmOverloads // assertFullyCovered() + @JvmOverloads // assertEmpty() fun example(p1: String = "p1", p2: String = "p2") { // assertFullyCovered() nop(p1 + p2) // assertFullyCovered() } // assertFullyCovered() From b7b8966dc2018ed00a7e278ff0bcc02d3613762c Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 17 Sep 2025 01:19:50 +0200 Subject: [PATCH 238/255] KotlinCoroutineFilter should filter Kotlin 2.2 suspending lambdas with parameters (#1945) --- .../KotlinCoroutineSuspendingLambdaTest.java | 27 +++++ .../KotlinCoroutineSuspendingLambdaTarget.kt | 43 ++++++++ .../filter/KotlinCoroutineFilterTest.java | 99 +++++++++++++++++++ .../filter/KotlinCoroutineFilter.java | 80 +++------------ org.jacoco.doc/docroot/doc/changes.html | 3 + 5 files changed, 183 insertions(+), 69 deletions(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineSuspendingLambdaTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineSuspendingLambdaTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineSuspendingLambdaTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineSuspendingLambdaTest.java new file mode 100644 index 0000000000..3eebad5556 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineSuspendingLambdaTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinCoroutineSuspendingLambdaTarget; + +/** + * Test of code coverage in {@link KotlinCoroutineSuspendingLambdaTarget}. + */ +public class KotlinCoroutineSuspendingLambdaTest extends ValidationTestBase { + + public KotlinCoroutineSuspendingLambdaTest() { + super(KotlinCoroutineSuspendingLambdaTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineSuspendingLambdaTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineSuspendingLambdaTarget.kt new file mode 100644 index 0000000000..a803f7f43b --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineSuspendingLambdaTarget.kt @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.coroutines.runBlocking + +/** + * Test target containing suspending lambdas. + */ +object KotlinCoroutineSuspendingLambdaTarget { + + private fun withParameter() { + fun exec(block: suspend (p: String) -> Unit): Unit = runBlocking { block("") } + fun noexec(block: suspend (p: String) -> Unit) = Unit + suspend fun suspensionPoint(p: String) = Unit + + exec { p -> // assertFullyCovered() + suspensionPoint(p) // assertFullyCovered() + } // assertFullyCovered() + + noexec { p -> // assertFullyCovered() + suspensionPoint(p) // assertNotCovered() + } // assertNotCovered() + + noexec { p -> suspensionPoint(p) } // assertPartlyCovered() + } + + @JvmStatic + fun main(args: Array) { + withParameter() + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java index 2054181367..7688d91348 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java @@ -221,6 +221,105 @@ public void should_filter_suspending_lambdas() { assertIgnored(m, range0, range1, range2); } + /** + *
    +	 * fun exec(block: suspend (p: String) -> Unit): Unit
    +	 *
    +	 * fun main() =
    +	 *     exec { p ->
    +	 *         suspensionPoint(p)
    +	 *     }
    +	 * 
    + * + * after + * change in Kotlin compiler version 2.2 + */ + @Test + public void should_filter_suspending_lambdas_with_parameters() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "invokeSuspend", "(Ljava/lang/Object;)Ljava/lang/Object;", null, + null); + + final Range range1 = new Range(); + m.visitVarInsn(Opcodes.ALOAD, 0); + range1.fromInclusive = m.instructions.getLast(); + m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$main$1", "L$0", + "Ljava/lang/Object;"); + m.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); + m.visitVarInsn(Opcodes.ASTORE, 2); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false); + m.visitVarInsn(Opcodes.ASTORE, 3); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$main$1", "label", "I"); + final Label dflt = new Label(); + final Label state0 = new Label(); + final Label state1 = new Label(); + m.visitTableSwitchInsn(0, 1, dflt, state0, state1); + + 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.visitVarInsn(Opcodes.ALOAD, 2); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/coroutines/Continuation"); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/jvm/internal/SpillingKt", + "nullOutSpilledVariable", + "(Ljava/lang/Object;)Ljava/lang/Object;", false); + m.visitFieldInsn(Opcodes.PUTFIELD, "ExampleKt$main$1", "L$0", + "Ljava/lang/Object;"); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitInsn(Opcodes.ICONST_1); + m.visitFieldInsn(Opcodes.PUTFIELD, "ExampleKt$main$1", "label", "I"); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", "suspensionPoint", + "(Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + false); + m.visitInsn(Opcodes.DUP); + final Range range2 = new Range(); + range2.fromInclusive = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 3); + final Label label6 = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, label6); + m.visitVarInsn(Opcodes.ALOAD, 3); + m.visitInsn(Opcodes.ARETURN); + + m.visitLabel(state1); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt", + "throwOnFailure", "(Ljava/lang/Object;)V", false); + m.visitVarInsn(Opcodes.ALOAD, 1); + range2.toInclusive = m.instructions.getLast(); + m.visitLabel(label6); + m.visitInsn(Opcodes.POP); + 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.visitLineNumber(35, dflt); + 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(m, range0, range1, range2); + } + /** *
     	 *     suspend fun example() {
    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 40a9b8c829..beaad593b6 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
    @@ -90,32 +90,23 @@ private void matchOptimizedTailCall(final MethodNode methodNode,
     
     		private void match(final MethodNode methodNode,
     				final IFilterOutput output) {
    -			cursor = skipNonOpcodes(methodNode.instructions.getFirst());
    -			if (cursor == null || cursor.getOpcode() != Opcodes.INVOKESTATIC) {
    -				cursor = null;
    -			} else {
    -				final MethodInsnNode m = (MethodInsnNode) cursor;
    -				if (!"kotlin/coroutines/intrinsics/IntrinsicsKt".equals(m.owner)
    -						|| !"getCOROUTINE_SUSPENDED".equals(m.name)
    -						|| !"()Ljava/lang/Object;".equals(m.desc)) {
    -					cursor = null;
    +			for (cursor = methodNode.instructions
    +					.getFirst(); cursor != null; cursor = cursor.getNext()) {
    +				if (cursor.getOpcode() == Opcodes.INVOKESTATIC) {
    +					final MethodInsnNode m = (MethodInsnNode) cursor;
    +					if ("kotlin/coroutines/intrinsics/IntrinsicsKt".equals(
    +							m.owner) && "getCOROUTINE_SUSPENDED".equals(m.name)
    +							&& "()Ljava/lang/Object;".equals(m.desc)) {
    +						break;
    +					}
     				}
     			}
    -
     			if (cursor == null) {
    -				cursor = skipNonOpcodes(methodNode.instructions.getFirst());
    -
    -				nextIsCreateStateInstance();
    -
    -				nextIsInvoke(Opcodes.INVOKESTATIC,
    -						"kotlin/coroutines/intrinsics/IntrinsicsKt",
    -						"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;");
    +				return;
     			}
     
     			final TableSwitchInsnNode s;
    -			if (cursor != null
    -					&& Opcodes.POP == skipNonOpcodes(cursor.getNext())
    -							.getOpcode()) {
    +			if (Opcodes.POP == skipNonOpcodes(cursor.getNext()).getOpcode()) {
     				// suspending lambda without suspension points
     				nextIs(Opcodes.POP);
     				s = nextIsStateSwitch();
    @@ -229,55 +220,6 @@ private void nextIsThrowOnFailure() {
     				nextIs(Opcodes.POP);
     			}
     		}
    -
    -		private void nextIsCreateStateInstance() {
    -			nextIs(Opcodes.INSTANCEOF);
    -
    -			nextIs(Opcodes.IFEQ);
    -			if (cursor == null) {
    -				return;
    -			}
    -			final AbstractInsnNode createStateInstance = skipNonOpcodes(
    -					((JumpInsnNode) cursor).label);
    -
    -			nextIs(Opcodes.ALOAD);
    -			nextIs(Opcodes.CHECKCAST);
    -			nextIs(Opcodes.ASTORE);
    -
    -			nextIs(Opcodes.ALOAD);
    -			nextIs(Opcodes.GETFIELD);
    -
    -			nextIs(Opcodes.LDC);
    -			nextIs(Opcodes.IAND);
    -			nextIs(Opcodes.IFEQ);
    -			if (cursor == null || skipNonOpcodes(
    -					((JumpInsnNode) cursor).label) != createStateInstance) {
    -				return;
    -			}
    -
    -			nextIs(Opcodes.ALOAD);
    -			nextIs(Opcodes.DUP);
    -			nextIs(Opcodes.GETFIELD);
    -
    -			nextIs(Opcodes.LDC);
    -			nextIs(Opcodes.ISUB);
    -			nextIs(Opcodes.PUTFIELD);
    -
    -			nextIs(Opcodes.GOTO);
    -			if (cursor == null) {
    -				return;
    -			}
    -			final AbstractInsnNode afterCoroutineStateCreated = skipNonOpcodes(
    -					((JumpInsnNode) cursor).label);
    -
    -			if (skipNonOpcodes(cursor.getNext()) != createStateInstance) {
    -				return;
    -			}
    -
    -			cursor = afterCoroutineStateCreated;
    -			nextIs(Opcodes.GETFIELD);
    -			nextIs(Opcodes.ASTORE);
    -		}
     	}
     
     }
    diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
    index 13941a8c61..1638e739dd 100644
    --- a/org.jacoco.doc/docroot/doc/changes.html
    +++ b/org.jacoco.doc/docroot/doc/changes.html
    @@ -34,6 +34,9 @@ 

    New Features

    suspendCoroutineUninterceptedOrReturn intrinsic is filtered out during generation of report (GitHub #1929). +
  • Part of bytecode generated by the Kotlin compiler for suspending lambdas with + parameters is filtered out during generation of report + (GitHub #1945).
  • Part of bytecode generated by the Kotlin Compose compiler plugin for pausable composition is filtered out during generation of report (GitHub #1911).
  • From 355abb5bb2d0e3ee91f0c4bc6e6d623d69fbdc5b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 17 Sep 2025 01:52:05 +0200 Subject: [PATCH 239/255] Happy birthday Java 25! (#1950) --- org.jacoco.doc/docroot/doc/changes.html | 2 ++ org.jacoco.doc/docroot/doc/environment.html | 2 +- org.jacoco.doc/docroot/doc/faq.html | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 1638e739dd..8278fd5f3a 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,6 +22,8 @@

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    New Features

      +
    • JaCoCo now officially supports Java 25 + (GitHub #1950).
    • Experimental support for Java 26 class files (GitHub #1870).
    • Branches added by the Kotlin compiler for default argument number 33 or higher diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html index 838c209b9a..69d72f3610 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, 22, 23, 24 and 25 JDKs. + 18, 19, 20, 21, 22, 23, 24, 25 and 26 JDKs.

      Build

      diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html index 537e7592be..505a06392d 100644 --- a/org.jacoco.doc/docroot/doc/faq.html +++ b/org.jacoco.doc/docroot/doc/faq.html @@ -45,8 +45,8 @@

      Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?

      What Java versions are supported by JaCoCo?

      - JaCoCo officially supports Java class files from version 1.0 to 24. Also - experimental support for class files of version 25 and 26 is provided. + JaCoCo officially supports Java class files from version 1.0 to 25. Also + experimental support for class files of version 26 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. From fd2b323b7f4aa7a9548b05cd5a444e3e1ff3c86b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 22 Sep 2025 23:39:27 +0200 Subject: [PATCH 240/255] KotlinCoroutineFilter should filter suspension points that return inline value classes (#1871) --- .../KotlinCoroutineInlineValueClassTest.java | 27 ++++++ .../KotlinCoroutineInlineValueClassTarget.kt | 35 +++++++ .../filter/KotlinCoroutineFilterTest.java | 94 +++++++++++++++++++ .../filter/KotlinCoroutineFilter.java | 25 +---- org.jacoco.doc/docroot/doc/changes.html | 4 + 5 files changed, 165 insertions(+), 20 deletions(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineInlineValueClassTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineInlineValueClassTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineInlineValueClassTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineInlineValueClassTest.java new file mode 100644 index 0000000000..f84c7ea5d4 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineInlineValueClassTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinCoroutineInlineValueClassTarget; + +/** + * Test of code coverage in {@link KotlinCoroutineInlineValueClassTarget}. + */ +public class KotlinCoroutineInlineValueClassTest extends ValidationTestBase { + + public KotlinCoroutineInlineValueClassTest() { + super(KotlinCoroutineInlineValueClassTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineInlineValueClassTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineInlineValueClassTarget.kt new file mode 100644 index 0000000000..bca7c92d5c --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineInlineValueClassTarget.kt @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.coroutines.runBlocking +import org.jacoco.core.test.validation.targets.Stubs.nop + +/** + * Test target with invocation of suspending function that returns inline value class. + */ +object KotlinCoroutineInlineValueClassTarget { + + suspend fun suspensionPointReturningInlineValueClass() = InlineValueClass("") + + @JvmInline + value class InlineValueClass(val value: String) + + @JvmStatic + fun main(args: Array) { + runBlocking { // assertFullyCovered() + nop(suspensionPointReturningInlineValueClass()) // assertFullyCovered() + } // assertFullyCovered() + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java index 7688d91348..fbbd23db17 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java @@ -610,6 +610,100 @@ public void should_filter_Kotlin_1_6_suspending_lambda_without_suspension_points assertIgnored(m, range0, range1); } + /** + *

      +	 *     fun example() =
      +	 *         runBlocking {
      +	 *             ...
      +	 *             suspensionPointReturningInlineValueClass()
      +	 *             ...
      +	 *         }
      +	 *
      +	 *     suspend fun suspensionPointReturningInlineValueClass() =
      +	 *         InlineValueClass("")
      +	 *
      +	 *     @kotlin.jvm.JvmInline
      +	 *     value class InlineValueClass(val value: String)
      +	 * 
      + */ + @Test + public void should_filter_suspending_lambdas_and_functions_when_suspension_point_returns_inline_value_class() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "invokeSuspend", + "(Ljava/lang/Object;)Ljava/lang/Object;", null, null); + + 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.visitVarInsn(Opcodes.ASTORE, 3); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I"); + final Label state0 = new Label(); + final Label state1 = new Label(); + final Label dflt = new Label(); + m.visitTableSwitchInsn(0, 1, dflt, state0, state1); + 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.visitVarInsn(Opcodes.ALOAD, 0); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/coroutines/Continuation"); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitInsn(Opcodes.ICONST_1); + m.visitFieldInsn(Opcodes.PUTFIELD, "ExampleKt$example$1", "label", "I"); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "ExampleKt", + "suspensionPointReturningInlineValueClass--KaAbg4", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false); + m.visitInsn(Opcodes.DUP); + + final Range range2 = new Range(); + range2.fromInclusive = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 3); + final Label continuationAfterLoadedResult = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationAfterLoadedResult); + m.visitVarInsn(Opcodes.ALOAD, 3); + m.visitInsn(Opcodes.ARETURN); + + m.visitLabel(state1); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt", + "throwOnFailure", "(Ljava/lang/Object;)V", false); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitTypeInsn(Opcodes.CHECKCAST, "InlineValueClass"); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "InlineValueClass", + "unbox-impl", "()Ljava/lang/String;", false); + range2.toInclusive = m.instructions.getLast(); + m.visitLabel(continuationAfterLoadedResult); + + m.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); + m.visitVarInsn(Opcodes.ASTORE, 2); + + 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.visitLineNumber(29, dflt); + 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(m, range0, range1, range2); + } + /** *
       	 *     suspend fun example() =
      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 beaad593b6..73c6b11c32 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
      @@ -138,11 +138,7 @@ private void match(final MethodNode methodNode,
       				cursor = i;
       				nextIsVar(Opcodes.ALOAD, "COROUTINE_SUSPENDED");
       				nextIs(Opcodes.IF_ACMPNE);
      -				if (cursor == null) {
      -					continue;
      -				}
      -				final AbstractInsnNode continuationAfterLoadedResult = skipNonOpcodes(
      -						((JumpInsnNode) cursor).label);
      +				final JumpInsnNode jumpToContinuationAfterLoadedResult = (JumpInsnNode) cursor;
       				nextIsVar(Opcodes.ALOAD, "COROUTINE_SUSPENDED");
       				nextIs(Opcodes.ARETURN);
       				if (cursor == null
      @@ -150,21 +146,10 @@ private void match(final MethodNode methodNode,
       								s.labels.get(suspensionPoint))) {
       					continue;
       				}
      -
      -				for (AbstractInsnNode j = i; j != null; j = j.getNext()) {
      -					cursor = j;
      -					nextIs(Opcodes.ALOAD);
      -					nextIsThrowOnFailure();
      -
      -					nextIs(Opcodes.ALOAD);
      -					if (cursor != null && skipNonOpcodes(cursor
      -							.getNext()) == continuationAfterLoadedResult) {
      -						ignore.add(i);
      -						ignore.add(cursor);
      -						suspensionPoint++;
      -						break;
      -					}
      -				}
      +				ignore.add(i);
      +				ignore.add(jumpToContinuationAfterLoadedResult.label
      +						.getPrevious());
      +				suspensionPoint++;
       			}
       
       			cursor = s.dflt;
      diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
      index 8278fd5f3a..3af3388bdc 100644
      --- a/org.jacoco.doc/docroot/doc/changes.html
      +++ b/org.jacoco.doc/docroot/doc/changes.html
      @@ -39,6 +39,10 @@ 

      New Features

    • Part of bytecode generated by the Kotlin compiler for suspending lambdas with parameters is filtered out during generation of report (GitHub #1945).
    • +
    • Part of bytecode generated by the Kotlin compiler for suspending functions and + lambdas with suspension points that return inline value class is filtered out + during generation of report + (GitHub #1871).
    • Part of bytecode generated by the Kotlin Compose compiler plugin for pausable composition is filtered out during generation of report (GitHub #1911).
    • From 5d10738d4a0587371f54a913cd65c2bad716074a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sun, 28 Sep 2025 01:51:54 +0200 Subject: [PATCH 241/255] Upgrade Maven Wrapper to 3.3.4 (#1955) --- .mvn/wrapper/maven-wrapper.properties | 18 +-------- mvnw | 50 ++++++++++++++++++++---- mvnw.cmd | 56 +++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 546a64e725..222cba3baf 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,20 +1,4 @@ -# 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 +wrapperVersion=3.3.4 distributionType=only-script distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip distributionSha256Sum=0d7125e8c91097b36edb990ea5934e6c68b4440eef4ea96510a0f6815e7eeadb diff --git a/mvnw b/mvnw index 19529ddf8c..bd8896bf22 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.2 +# Apache Maven Wrapper startup batch script, version 3.3.4 # # Optional ENV vars # ----------------- @@ -105,14 +105,17 @@ trim() { printf "%s" "${1}" | tr -d '[:space:]' } +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + # 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" +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" case "${distributionUrl##*/}" in maven-mvnd-*bin.*) @@ -130,7 +133,7 @@ maven-mvnd-*bin.*) 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/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; esac # apply MVNW_REPOURL and calculate MAVEN_HOME @@ -227,7 +230,7 @@ if [ -n "${distributionSha256Sum-}" ]; then 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 + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then distributionSha256Result=true fi elif command -v shasum >/dev/null; then @@ -252,8 +255,41 @@ if command -v unzip >/dev/null; then 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" + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" clean || : exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index b150b91ed5..5761d94892 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -19,7 +19,7 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM Apache Maven Wrapper startup batch script, version 3.3.4 @REM @REM Optional ENV vars @REM MVNW_REPOURL - repo url base for downloading maven distribution @@ -40,7 +40,7 @@ @SET __MVNW_ARG0_NAME__= @SET MVNW_USERNAME= @SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) @echo Cannot start maven from wrapper >&2 && exit /b 1 @GOTO :EOF : end batch / begin powershell #> @@ -73,16 +73,30 @@ switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { # 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,'')" + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/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" + +$MAVEN_M2_PATH = "$HOME/.m2" if ($env:MAVEN_USER_HOME) { - $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" } -$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::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) { @@ -134,7 +148,33 @@ if ($distributionSha256Sum) { # 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 + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null try { Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null } catch { From 722ab408e6d1329929e221b8d3921db23a528cfb Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 29 Sep 2025 09:36:12 +0200 Subject: [PATCH 242/255] Upgrade scala-maven-plugin to 4.5.6 (#1957) --- org.jacoco.core.test.validation.scala/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index 8667081dd8..d3183cbf36 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -45,7 +45,7 @@ net.alchim31.maven scala-maven-plugin - 4.4.0 + 4.5.6 compile From 8b18051d8babe55d626c6d6d26715b0f0bed6cb7 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 29 Sep 2025 16:08:44 +0200 Subject: [PATCH 243/255] Add configuration for Dependabot to simplify updates of Groovy (#1960) --- .github/dependabot.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9271f24667..db72d0172c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -51,3 +51,16 @@ updates: - "language: Kotlin" allow: - dependency-name: "org.jetbrains.kotlin:*" + - package-ecosystem: "maven" + directory: "/org.jacoco.core.test.validation.groovy" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "component: test" + - "language: Groovy" + allow: + - dependency-name: "org.codehaus.groovy:*" + ignore: + - dependency-name: "org.codehaus.groovy:*" + versions: ">=4.0.0" From daaa3bbbf3378dfe23bd73efe802e9a107d466f9 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Mon, 29 Sep 2025 18:49:31 +0200 Subject: [PATCH 244/255] Upgrade Groovy to 3.0.25 (#1958) --- .../pom.xml | 3 ++- org.jacoco.core.test.validation/pom.xml | 24 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index 019eda0378..b759cdf288 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -27,7 +27,8 @@ 3.0.0 - 3.0.22 + + 3.0.25 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 0a7c5f1f83..80c99b848a 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -368,7 +368,7 @@ 18 - + 16 18 @@ -395,7 +395,7 @@ 19 - + 16 19 @@ -422,7 +422,7 @@ 20 - + 16 20 @@ -449,7 +449,7 @@ 21 - + 16 21 @@ -477,7 +477,7 @@ 22 - + 16 22 @@ -505,7 +505,7 @@ 23 - + 16 23 @@ -534,7 +534,7 @@ 23 - + 16 24 @@ -547,7 +547,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 @@ -565,7 +565,7 @@ 23 - + 16 25 @@ -578,9 +578,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 @@ -596,7 +594,7 @@ 23 - + 16 26 @@ -609,7 +607,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 7994089f2be32b582c8c8773d82fa5635b2289e5 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 30 Sep 2025 10:00:17 +0200 Subject: [PATCH 245/255] Kotlin since version 2.2.0 supports compilation into Java 24 bytecode (#1959) --- org.jacoco.core.test.validation.kotlin/pom.xml | 1 + org.jacoco.core.test.validation/pom.xml | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 6195ad4005..602d76bad2 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -25,6 +25,7 @@ JaCoCo :: Test :: Core :: Validation Kotlin + 2.2.20 diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index 80c99b848a..c4b2d85bca 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -532,8 +532,7 @@ - - 23 + 24 16 @@ -563,8 +562,8 @@ - - 23 + + 24 16 @@ -592,8 +591,8 @@ - - 23 + + 24 16 From faa289d2a370fa4f724bed3a09e8591be08cd6c2 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:25:18 +0200 Subject: [PATCH 246/255] KotlinSafeCallOperatorFilter should not be affected by presence of pseudo instructions (#1956) --- .../targets/KotlinSafeCallOperatorTarget.kt | 23 +++++++++++++++++++ .../KotlinSafeCallOperatorFilterTest.java | 5 +++- .../filter/KotlinSafeCallOperatorFilter.java | 21 ++++++++++++++--- org.jacoco.doc/docroot/doc/changes.html | 3 +++ 4 files changed, 48 insertions(+), 4 deletions(-) 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 2f55b3dd5f..ec55a8f902 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 @@ -57,6 +57,28 @@ object KotlinSafeCallOperatorTarget { } private fun safeCallChainMultiline() { + fun nullOnly(a: A?): String? = + a // assertNotCovered() + ?.b // assertPartlyCovered(1, 1) + ?.c // assertPartlyCovered(1, 1) + + fun nonNullOnly(a: A?): String? = + a // assertFullyCovered() + ?.b // assertPartlyCovered(1, 1) + ?.c // assertFullyCovered(1, 1) + + fun fullCoverage(a: A?): String? = + a // assertFullyCovered() + ?.b // assertFullyCovered(0, 2) + ?.c // assertFullyCovered(0, 2) + + nullOnly(null) + nonNullOnly(A(B(""))) + fullCoverage(null) + fullCoverage(A(B(""))) + } + + private fun safeCallChainMultiline2() { fun nullOnly(a: A?): String? = a?.also { // assertPartlyCovered(1, 1) nop(it) // assertNotCovered() @@ -125,6 +147,7 @@ object KotlinSafeCallOperatorTarget { safeCall() safeCallChain() safeCallChainMultiline() + safeCallChainMultiline2() safeCallChainException() safeCallFollowedByElvis() safeCallChainFollowedByElvis() 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 index 4a222a6ec7..27feed28eb 100644 --- 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 @@ -89,7 +89,7 @@ public void should_filter_optimized_safe_call_chain() { * fun example(a: A?): String? = * a * ?.b - * ?.c + * ?.c // line 6 *
      */ @Test @@ -108,6 +108,9 @@ public void should_filter_unoptimized_safe_call_chain() { m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "A", "getB", "()LB;", false); m.visitVarInsn(Opcodes.ASTORE, 1); + final Label lineNumberLabel = new Label(); + m.visitLabel(lineNumberLabel); + m.visitLineNumber(6, lineNumberLabel); m.visitVarInsn(Opcodes.ALOAD, 1); m.visitJumpInsn(Opcodes.IFNULL, label1); final AbstractInsnNode ifNullInstruction2 = m.instructions.getLast(); 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 index 8fce63c698..e268720913 100644 --- 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 @@ -108,12 +108,12 @@ private static Collection> findChains( continue; } } else if (target.getOpcode() == Opcodes.ACONST_NULL) { - if (i.getPrevious().getOpcode() != Opcodes.ALOAD) { + final AbstractInsnNode p1 = preceding(i); + if (p1.getOpcode() != Opcodes.ALOAD) { continue; } if (chain != null) { - final AbstractInsnNode p1 = i.getPrevious(); - final AbstractInsnNode p2 = p1.getPrevious(); + final AbstractInsnNode p2 = preceding(p1); if (p2 == null || p2.getOpcode() != Opcodes.ASTORE || ((VarInsnNode) p1).var != ((VarInsnNode) p2).var) { continue; @@ -131,4 +131,19 @@ private static Collection> findChains( return chains.values(); } + /** + * @return non pseudo-instruction preceding given + */ + private static AbstractInsnNode preceding(AbstractInsnNode i) { + if (i == null) { + return null; + } + do { + i = i.getPrevious(); + } while (i != null && (i.getType() == AbstractInsnNode.LABEL + || i.getType() == AbstractInsnNode.LINE + || i.getType() == AbstractInsnNode.FRAME)); + return i; + } + } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 3af3388bdc..c1149d03d3 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -32,6 +32,9 @@

      New Features

    • Part of bytecode generated by the Kotlin compiler for elvis operator that follows safe call operator is filtered out during generation of report (GitHub #1814).
    • +
    • Part of bytecode generated by the Kotlin compiler for more cases of chained + safe call operators is filtered out during generation of report + (GitHub #1956).
    • Part of bytecode generated by the Kotlin compiler for invocations of suspendCoroutineUninterceptedOrReturn intrinsic is filtered out during generation of report From c7bd3f4e96540d1a8f58690d5d52a94eebf4c471 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 12:37:29 +0000 Subject: [PATCH 247/255] Upgrade spotless-maven-plugin to 3.0.0 (#1961) --- 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 c964fb2797..d0e32e24f4 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -450,7 +450,7 @@ com.diffplug.spotless spotless-maven-plugin - 2.46.1 + 3.0.0 org.sonarsource.scanner.maven From b0f8e23d91d59431124b2863b8e35bdd1b71f7b9 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Tue, 7 Oct 2025 01:25:07 +0200 Subject: [PATCH 248/255] KotlinSafeCallOperatorFilter should filter "unoptimized" safe call followed by elvis (#1954) --- .../targets/KotlinSafeCallOperatorTarget.kt | 49 +++++++++ .../KotlinSafeCallOperatorFilterTest.java | 103 ++++++++++++++++++ .../filter/KotlinSafeCallOperatorFilter.java | 84 ++++++++++++-- org.jacoco.doc/docroot/doc/changes.html | 3 +- 4 files changed, 228 insertions(+), 11 deletions(-) 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 ec55a8f902..a637175f24 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 @@ -126,6 +126,28 @@ object KotlinSafeCallOperatorTarget { fullCoverage(B("")) } + private fun safeCallFollowedByElvisMultiline() { + fun nullOnly(b: B?): String = + b // assertPartlyCovered(1, 1) + ?.c // assertPartlyCovered(1, 1) + ?: "" // assertFullyCovered() + + fun nonNullOnly(b: B?): String = + b // assertFullyCovered(1, 1) + ?.c // assertFullyCovered(1, 1) + ?: "" // assertPartlyCovered() + + fun fullCoverage(b: B?): String = + b // assertFullyCovered(0, 2) + ?.c // assertFullyCovered(0, 2) + ?: "" // assertFullyCovered() + + nullOnly(null) + nonNullOnly(B("")) + fullCoverage(null) + fullCoverage(B("")) + } + private fun safeCallChainFollowedByElvis() { fun nullOnly(a: A?): String = a?.b?.c ?: "" // assertPartlyCovered(3, 3) @@ -142,6 +164,31 @@ object KotlinSafeCallOperatorTarget { fullCoverage(A(B(""))) } + private fun safeCallChainFollowedByElvisMultiline() { + fun nullOnly(a: A?): String = + a // assertPartlyCovered(1, 1) + ?.b // assertPartlyCovered(1, 1) + ?.c // assertPartlyCovered(1, 1) + ?: "" // assertFullyCovered() + + fun nonNullOnly(a: A?): String = + a // assertFullyCovered(1, 1) + ?.b // assertFullyCovered(1, 1) + ?.c // assertFullyCovered(1, 1) + ?: "" // assertPartlyCovered() + + fun fullCoverage(a: A?): String = + a // assertFullyCovered(0, 2) + ?.b // assertFullyCovered(0, 2) + ?.c // assertFullyCovered(0, 2) + ?: "" // assertFullyCovered() + + nullOnly(null) + nonNullOnly(A(B(""))) + fullCoverage(null) + fullCoverage(A(B(""))) + } + @JvmStatic fun main(args: Array) { safeCall() @@ -150,7 +197,9 @@ object KotlinSafeCallOperatorTarget { safeCallChainMultiline2() safeCallChainException() safeCallFollowedByElvis() + safeCallFollowedByElvisMultiline() safeCallChainFollowedByElvis() + safeCallChainFollowedByElvisMultiline() } } 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 index 27feed28eb..6ff518e0cb 100644 --- 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 @@ -233,4 +233,107 @@ public void should_filter_safe_call_chain_followed_by_elvis() { assertReplacedBranches(m, replacements); } + /** + *
      +	 * data class B(val c: String)
      +	 * fun example(b: B?): String =
      +	 *     b
      +	 *       ?.c
      +	 *       ?: ""
      +	 * 
      + */ + @Test + public void should_filter_unoptimized_safe_call_followed_by_elvis() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "(LB;)Ljava/lang/String;", null, null); + m.visitVarInsn(Opcodes.ALOAD, 0); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFNULL, label); + final AbstractInsnNode ifNullInstruction1 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC", + "()Ljava/lang/String;", false); + m.visitVarInsn(Opcodes.ASTORE, 1); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitJumpInsn(Opcodes.IFNULL, label); + final AbstractInsnNode ifNullInstruction2 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 1); + final Label next = new Label(); + m.visitJumpInsn(Opcodes.GOTO, next); + m.visitLabel(label); + m.visitLdcInsn(""); + final AbstractInsnNode nullTarget = m.instructions.getLast(); + m.visitLabel(next); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(m); + final HashMap> replacements = new HashMap>(); + replacements.put(ifNullInstruction1, Arrays.asList( // + new Replacement(0, ifNullInstruction1, 0), + new Replacement(1, nullTarget, 0))); + replacements.put(ifNullInstruction2, Arrays.asList( // + new Replacement(0, ifNullInstruction2, 0), + new Replacement(1, nullTarget, 0))); + assertReplacedBranches(m, replacements); + } + + /** + *
      +	 * data class A(val b: B)
      +	 * data class B(val c: String)
      +	 * fun example(a: A?): String? =
      +	 *     a
      +	 *         ?.b
      +	 *         ?.c
      +	 *         ?: ""
      +	 * 
      + */ + @Test + public void should_filter_unoptimized_safe_call_chain_followed_by_elvis() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", "(LA;)Ljava/lang/String;", null, null); + m.visitVarInsn(Opcodes.ALOAD, 0); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFNULL, label); + final AbstractInsnNode ifNullInstruction1 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "A", "getB", "()LB;", false); + m.visitVarInsn(Opcodes.ASTORE, 1); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitJumpInsn(Opcodes.IFNULL, label); + final AbstractInsnNode ifNullInstruction2 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "B", "getC", + "()Ljava/lang/String;", false); + m.visitVarInsn(Opcodes.ASTORE, 2); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitJumpInsn(Opcodes.IFNULL, label); + final AbstractInsnNode ifNullInstruction3 = m.instructions.getLast(); + m.visitVarInsn(Opcodes.ALOAD, 2); + final Label next = new Label(); + m.visitJumpInsn(Opcodes.GOTO, next); + m.visitLabel(label); + m.visitLdcInsn(""); + final AbstractInsnNode nullTarget = m.instructions.getLast(); + m.visitLabel(next); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(m); + final HashMap> replacements = new HashMap>(); + replacements.put(ifNullInstruction1, Arrays.asList( // + new Replacement(0, ifNullInstruction1, 0), + new Replacement(1, nullTarget, 0))); + replacements.put(ifNullInstruction2, Arrays.asList( // + new Replacement(0, ifNullInstruction2, 0), + new Replacement(1, nullTarget, 0))); + replacements.put(ifNullInstruction3, Arrays.asList( // + new Replacement(0, ifNullInstruction3, 0), + new Replacement(1, nullTarget, 0))); + assertReplacedBranches(m, replacements); + } + } 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 index e268720913..2d0b67fdc6 100644 --- 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 @@ -90,6 +90,31 @@ public void filter(final MethodNode methodNode, * label: * ACONST_NULL *
    + * + * "unoptimized" safe call operator(s) followed by elvis operator: + * + *
    +	 * ALOAD v0
    +	 * IFNULL nullCase
    +	 * ... // call 0
    +	 *
    +	 * ASTORE v1
    +	 * ALOAD v1
    +	 * IFNULL nullCase
    +	 * ... // call 1
    +	 *
    +	 * ...
    +	 *
    +	 * ASTORE vN
    +	 * ALOAD vN
    +	 * IFNULL nullCase
    +	 * ALOAD vN
    +	 * GOTO nonNullCase
    +	 * nullCase:
    +	 * ... // right hand side of elvis operator
    +	 * nonNullCase:
    +	 * ...
    +	 * 
    */ private static Collection> findChains( final MethodNode methodNode) { @@ -108,18 +133,19 @@ private static Collection> findChains( continue; } } else if (target.getOpcode() == Opcodes.ACONST_NULL) { - final AbstractInsnNode p1 = preceding(i); - if (p1.getOpcode() != Opcodes.ALOAD) { + final AbstractInsnNode p1 = preceding(i, Opcodes.ALOAD); + if (p1 == null) { continue; } if (chain != null) { - final AbstractInsnNode p2 = preceding(p1); - if (p2 == null || p2.getOpcode() != Opcodes.ASTORE + final AbstractInsnNode p2 = preceding(p1, Opcodes.ASTORE); + if (p2 == null || ((VarInsnNode) p1).var != ((VarInsnNode) p2).var) { continue; } } - } else { + } else if (!isUnoptimizedSafeCallFollowedByElvis(jump, target, + chain)) { continue; } if (chain == null) { @@ -131,19 +157,57 @@ private static Collection> findChains( return chains.values(); } + private static boolean isUnoptimizedSafeCallFollowedByElvis( + final JumpInsnNode jump, final AbstractInsnNode target, + final ArrayList chain) { + if (target.getType() == AbstractInsnNode.JUMP_INSN + || target.getType() == AbstractInsnNode.TABLESWITCH_INSN + || target.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { + return false; + } + final AbstractInsnNode p1 = preceding(jump, Opcodes.ALOAD); + if (p1 == null) { + return false; + } else if (chain == null) { + final AbstractInsnNode gotoInstruction = preceding(jump.label, + Opcodes.GOTO); + final AbstractInsnNode loadInstruction1 = preceding(gotoInstruction, + Opcodes.ALOAD); + final AbstractInsnNode ifNullInstruction = preceding( + loadInstruction1, Opcodes.IFNULL); + final AbstractInsnNode loadInstruction2 = preceding( + ifNullInstruction, Opcodes.ALOAD); + final AbstractInsnNode storeInstruction = preceding( + loadInstruction2, Opcodes.ASTORE); + return storeInstruction != null + && ((JumpInsnNode) ifNullInstruction).label == jump.label + && ((VarInsnNode) loadInstruction1).var == ((VarInsnNode) loadInstruction2).var + && ((VarInsnNode) loadInstruction1).var == ((VarInsnNode) storeInstruction).var; + } else { + final AbstractInsnNode p2 = preceding(p1, Opcodes.ASTORE); + return p2 != null + && ((VarInsnNode) p1).var == ((VarInsnNode) p2).var; + } + } + /** - * @return non pseudo-instruction preceding given + * @return non pseudo-instruction preceding given if it has given opcode, + * {@code null} otherwise */ - private static AbstractInsnNode preceding(AbstractInsnNode i) { + private static AbstractInsnNode preceding(AbstractInsnNode i, + final int opcode) { if (i == null) { return null; } do { i = i.getPrevious(); - } while (i != null && (i.getType() == AbstractInsnNode.LABEL + if (i == null) { + return null; + } + } while (i.getType() == AbstractInsnNode.LABEL || i.getType() == AbstractInsnNode.LINE - || i.getType() == AbstractInsnNode.FRAME)); - return i; + || i.getType() == AbstractInsnNode.FRAME); + return i.getOpcode() == opcode ? i : null; } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index c1149d03d3..b4d6d46889 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -31,7 +31,8 @@

    New Features

    (GitHub #1655).
  • Part of bytecode generated by the Kotlin compiler for elvis operator that follows safe call operator is filtered out during generation of report - (GitHub #1814).
  • + (GitHub #1814, + #1954).
  • Part of bytecode generated by the Kotlin compiler for more cases of chained safe call operators is filtered out during generation of report (GitHub #1956).
  • From c2fe5cc54472f188c0d0f1158a0f987295217138 Mon Sep 17 00:00:00 2001 From: Ed Merks Date: Tue, 7 Oct 2025 01:58:04 +0200 Subject: [PATCH 249/255] Upgrade ASM to 9.9 (#1965) --- org.jacoco.build/licenses/{asm-9.8.html => asm-9.9.html} | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) rename org.jacoco.build/licenses/{asm-9.8.html => asm-9.9.html} (96%) diff --git a/org.jacoco.build/licenses/asm-9.8.html b/org.jacoco.build/licenses/asm-9.9.html similarity index 96% rename from org.jacoco.build/licenses/asm-9.8.html rename to org.jacoco.build/licenses/asm-9.9.html index f74f83dc13..fb2619b4d5 100644 --- a/org.jacoco.build/licenses/asm-9.8.html +++ b/org.jacoco.build/licenses/asm-9.9.html @@ -1,7 +1,7 @@

    ASM

    - ASM 9.8 is subject to the terms and + ASM 9.9 is subject to the terms and conditions of the following license:

    diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index d0e32e24f4..d17675d3e3 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -139,7 +139,7 @@ ${jvm.args} - 9.8 + 9.9 1.9.16 2.0.28 4.13.2 diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index b4d6d46889..b857f12fa3 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -66,6 +66,12 @@

    Fixed bugs

    (GitHub #1819). +

    Non-functional Changes

    +
      +
    • JaCoCo now depends on ASM 9.9 + (GitHub #1965).
    • +
    +

    Release 0.8.13 (2025/04/02)

    New Features

    From 5e35fd5e1968c9477948f24991368b872e8014b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 22:40:17 +0200 Subject: [PATCH 250/255] Upgrade maven-dependency-plugin to 3.9.0 (#1966) --- 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 d17675d3e3..86644961a6 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -318,7 +318,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.8.1 + 3.9.0 org.apache.maven.plugins From d07bc6b7e47959503f878563cc4d18060223f2de Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 8 Oct 2025 00:33:18 +0200 Subject: [PATCH 251/255] Add filter for bytecode generated by Kotlin serialization compiler plugin (#1885) --- .../pom.xml | 17 ++ .../kotlin/KotlinSerializableTest.java | 34 ++++ .../targets/KotlinSerializableTarget.kt | 61 ++++++ .../filter/KotlinSerializableFilterTest.java | 174 ++++++++++++++++++ .../internal/analysis/filter/Filters.java | 1 + .../filter/KotlinSerializableFilter.java | 90 +++++++++ org.jacoco.doc/docroot/doc/changes.html | 2 + 7 files changed, 379 insertions(+) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableTarget.kt create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 602d76bad2..2713203166 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -44,6 +44,11 @@ kotlinx-coroutines-core 1.8.0
    + + org.jetbrains.kotlinx + kotlinx-serialization-core-jvm + 1.6.3 +
    @@ -68,6 +73,18 @@ + + + kotlinx-serialization + + + + + org.jetbrains.kotlin + kotlin-maven-serialization + ${kotlin.version} + +
    diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java new file mode 100644 index 0000000000..1afc08cf5a --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinSerializableTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinSerializableTarget}. + */ +public class KotlinSerializableTest extends ValidationTestBase { + + public KotlinSerializableTest() { + super(KotlinSerializableTarget.class); + } + + @Test + public void test_method_count() { + assertMethodCount( + /* main + 3 constructors + 3 getters + 1 method in companion */8); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableTarget.kt new file mode 100644 index 0000000000..717e4ca325 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableTarget.kt @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * Test target with [Serializable] class. + */ +object KotlinSerializableTarget { + + @Serializable // assertFullyCovered() + data class Example( // assertFullyCovered() + @SerialName("d") val data: String // assertFullyCovered() + ) // assertEmpty() + + @Serializable(with = CustomSerializer::class) // assertFullyCovered() + data class ExampleWithCustomSerializer( // assertFullyCovered() + val data: String // assertFullyCovered() + ) // assertEmpty() + + object CustomSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Example", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: ExampleWithCustomSerializer) = encoder.encodeString(value.data) + override fun deserialize(decoder: Decoder): ExampleWithCustomSerializer = + ExampleWithCustomSerializer(decoder.decodeString()) + } + + data class ExampleWithHandWrittenCompanion( + val data: String + ) { + companion object { + fun serializer(): KSerializer = CustomSerializer // assertNotCovered() + } + } + + @JvmStatic + fun main(args: Array) { + Example("").data + ExampleWithCustomSerializer("").data + ExampleWithHandWrittenCompanion("") + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java new file mode 100644 index 0000000000..fa1841417f --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 org.junit.Test; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit test for {@link KotlinSerializableFilter}. + */ +public class KotlinSerializableFilterTest extends FilterTestBase { + + private final IFilter filter = new KotlinSerializableFilter(); + + /** + *
    +	 * @kotlinx.serialization.Serializable
    +	 * data class Example(val data: String)
    +	 * 
    + */ + @Test + public void should_filter_synthetic_writeSelf_method() { + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC + | Opcodes.ACC_SYNTHETIC, + "write$Self$module_name", + "(Lpkg$Example;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V", + null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
    +	 * @kotlinx.serialization.Serializable
    +	 * data class Example(val data: String)
    +	 * 
    + */ + @Test + public void should_filter_synthetic_constructor() { + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, "", + "(ILjava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V", + null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + * Kotlin 2.1.21 for + * + *
    +	 * @kotlinx.serialization.Serializable // line 1
    +	 * data class Example(val data: String)
    +	 * 
    + */ + @Test + public void should_filter_generated_serializer_method() { + context.className = "Example$Companion"; + + final MethodNode initMethod = new MethodNode(Opcodes.ACC_PRIVATE, + "", "()V", null, null); + // no line numbers + filter.filter(initMethod, context, output); + + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "serializer", + "()Lkotlinx/serialization/KSerializer;", + "()Lkotlinx/serialization/KSerializer;", null); + final Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(1, label0); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example$$serializer", "INSTANCE", + "LExample$$serializer;"); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlinx/serialization/KSerializer"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
    +	 * @kotlinx.serialization.Serializable
    +	 * data class Example(val data: String) {
    +	 *     companion object // line 2
    +	 * }
    +	 * 
    + */ + @Test + public void should_filter_generated_serializer_method_in_hand_written_companion() { + context.className = "Example$Companion"; + + final MethodNode initMethod = new MethodNode(Opcodes.ACC_PRIVATE, + "", "()V", null, null); + final Label initMethodLineNumberLabel = new Label(); + initMethod.visitLabel(initMethodLineNumberLabel); + initMethod.visitLineNumber(2, initMethodLineNumberLabel); + filter.filter(initMethod, context, output); + + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "serializer", + "()Lkotlinx/serialization/KSerializer;", + "()Lkotlinx/serialization/KSerializer;", null); + final Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(2, label0); + m.visitFieldInsn(Opcodes.GETSTATIC, "Example$$serializer", "INSTANCE", + "LExample$$serializer;"); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlinx/serialization/KSerializer"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
    +	 * data class Example(val data: String) {
    +	 *     companion object { // line 2
    +	 *         fun serializer(): KSerializer<Example> = CustomSerializer
    +	 *     }
    +	 * }
    +	 * 
    + */ + @Test + public void should_not_filter_hand_written_serializer_method() { + context.className = "Example$Companion"; + + final MethodNode initMethod = new MethodNode(Opcodes.ACC_PRIVATE, + "", "()V", null, null); + final Label initMethodLineNumberLabel = new Label(); + initMethod.visitLabel(initMethodLineNumberLabel); + initMethod.visitLineNumber(2, initMethodLineNumberLabel); + filter.filter(initMethod, context, output); + + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "serializer", + "()Lkotlinx/serialization/KSerializer;", + "()Lkotlinx/serialization/KSerializer;", null); + final Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(3, label0); + m.visitFieldInsn(Opcodes.GETSTATIC, "CustomSerializer", "INSTANCE", + "LCustomSerializer;"); + m.visitTypeInsn(Opcodes.CHECKCAST, "kotlinx/serialization/KSerializer"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(m); + } + +} 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 2e66568e1c..f7f66022b3 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 @@ -79,6 +79,7 @@ private static IFilter allKotlinFilters() { return new FilterSet( // new KotlinGeneratedFilter(), // new KotlinSyntheticAccessorsFilter(), // + new KotlinSerializableFilter(), // new KotlinEnumFilter(), // new KotlinJvmOverloadsFilter(), // new KotlinSafeCallOperatorFilter(), // diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java new file mode 100644 index 0000000000..ed43310162 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters methods generated by Kotlin + * serialization compiler plugin. + */ +final class KotlinSerializableFilter implements IFilter { + + private int lineNumber = -2; + + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + if (context.getClassName().endsWith("$Companion")) { + if (methodNode.name.equals("") + && methodNode.desc.equals("()V")) { + lineNumber = -1; + for (final AbstractInsnNode i : methodNode.instructions) { + if (i.getType() == AbstractInsnNode.LINE) { + lineNumber = ((LineNumberNode) i).line; + return; + } + } + } + if (methodNode.name.equals("serializer") + && methodNode.desc + .equals("()Lkotlinx/serialization/KSerializer;") + && new Matcher().match(methodNode, lineNumber)) { + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + return; + } + + if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) { + return; + } + + if (methodNode.name.startsWith("write$Self$")) { + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + return; + } + + final Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); + if (argumentTypes.length > 1 && argumentTypes[argumentTypes.length - 1] + .getClassName() + .equals("kotlinx.serialization.internal.SerializationConstructorMarker")) { + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + } + } + + private static class Matcher extends AbstractMatcher { + public boolean match(final MethodNode methodNode, + final int lineNumber) { + cursor = methodNode.instructions.getFirst(); + nextIs(Opcodes.GETSTATIC); + final FieldInsnNode getStaticInstruction = (FieldInsnNode) cursor; + final AbstractInsnNode lineNumberInstruction = cursor.getPrevious(); + nextIsType(Opcodes.CHECKCAST, "kotlinx/serialization/KSerializer"); + nextIs(Opcodes.ARETURN); + return cursor != null + && getStaticInstruction.name.equals("INSTANCE") + && (lineNumberInstruction instanceof LineNumberNode) + && (lineNumber == -1 + || lineNumber == ((LineNumberNode) lineNumberInstruction).line); + } + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index b857f12fa3..71a5478aa9 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -50,6 +50,8 @@

    New Features

  • Part of bytecode generated by the Kotlin Compose compiler plugin for pausable composition is filtered out during generation of report (GitHub #1911).
  • +
  • Methods generated by the Kotlin serialization compiler plugin are filtered out + (GitHub #1885).
  • Fixed bugs

    From 098112865bb957084cc9abc1a9ca3f5bbff7219b Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Wed, 8 Oct 2025 01:56:31 +0200 Subject: [PATCH 252/255] Migrate release staging to the Central Publisher Portal (#1968) --- 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 86644961a6..81c6d48afb 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -114,7 +114,7 @@ sonatype-nexus-staging Nexus Release Repository - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/ sonatype-nexus-snapshots From 89c4bd5ff39deae410f2a899289fe96739a63c13 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:34:52 +0200 Subject: [PATCH 253/255] Fix NPE in KotlinSerializableFilter (#1970) --- .../kotlin/KotlinSerializableEnumTest.java | 27 ++++++++++++ .../kotlin/KotlinSerializableSealedTest.java | 27 ++++++++++++ .../targets/KotlinSerializableEnumTarget.kt | 32 ++++++++++++++ .../targets/KotlinSerializableSealedTarget.kt | 33 ++++++++++++++ .../filter/KotlinSerializableFilterTest.java | 44 +++++++++++++++++++ .../filter/KotlinSerializableFilter.java | 3 ++ org.jacoco.doc/docroot/doc/changes.html | 3 +- 7 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java new file mode 100644 index 0000000000..bc2508690c --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinSerializableEnumTarget; + +/** + * Test of code coverage in {@link KotlinSerializableEnumTarget}. + */ +public class KotlinSerializableEnumTest extends ValidationTestBase { + + public KotlinSerializableEnumTest() { + super(KotlinSerializableEnumTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java new file mode 100644 index 0000000000..d225d9a374 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinSerializableSealedTarget; + +/** + * Test of code coverage in {@link KotlinSerializableSealedTarget}. + */ +public class KotlinSerializableSealedTest extends ValidationTestBase { + + public KotlinSerializableSealedTest() { + super(KotlinSerializableSealedTarget.class); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt new file mode 100644 index 0000000000..de3dae92a1 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.serialization.Serializable + +/** + * Test target with [Serializable] `enum class`. + */ +object KotlinSerializableEnumTarget { + + @Serializable + enum class E { + V + } + + @JvmStatic + fun main(args: Array) { + E.V + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt new file mode 100644 index 0000000000..0e639ab198 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.serialization.Serializable + +/** + * Test target with [Serializable] `sealed class`. + */ +object KotlinSerializableSealedTarget { + + @Serializable + private sealed class Sealed { + @Serializable + data class A(val data: String): Sealed() + } + + @JvmStatic + fun main(args: Array) { + Sealed.A("").data + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java index fa1841417f..ab678e75cd 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java @@ -171,4 +171,48 @@ public void should_not_filter_hand_written_serializer_method() { assertIgnored(m); } + /** + *
    +	 * @kotlinx.serialization.Serializable // line 1
    +	 * enum class Example {
    +	 *     V
    +	 * }
    +	 * 
    + * + *
    +	 * @kotlinx.serialization.Serializable // line 1
    +	 * sealed class Example {
    +	 * }
    +	 * 
    + */ + @Test + public void should_filter_generated_serializer_method_in_companions_of_enum_and_sealed_class() { + context.className = "Example$Companion"; + + final MethodNode initMethod = new MethodNode(Opcodes.ACC_PRIVATE, + "", "()V", null, null); + final Label initMethodLineNumberLabel = new Label(); + initMethod.visitLabel(initMethodLineNumberLabel); + initMethod.visitLineNumber(1, initMethodLineNumberLabel); + filter.filter(initMethod, context, output); + + final MethodNode m = new MethodNode( + Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "serializer", + "()Lkotlinx/serialization/KSerializer;", + "()Lkotlinx/serialization/KSerializer;", null); + final Label label0 = new Label(); + m.visitLabel(label0); + m.visitLineNumber(1, label0); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Example$Companion", + "get$cachedSerializer", "()Lkotlinx/serialization/KSerializer;", + false); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + // FIXME https://github.com/jacoco/jacoco/issues/1971 + assertIgnored(m); + } + } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java index ed43310162..87dc23accd 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java @@ -76,6 +76,9 @@ public boolean match(final MethodNode methodNode, cursor = methodNode.instructions.getFirst(); nextIs(Opcodes.GETSTATIC); final FieldInsnNode getStaticInstruction = (FieldInsnNode) cursor; + if (cursor == null) { + return false; + } final AbstractInsnNode lineNumberInstruction = cursor.getPrevious(); nextIsType(Opcodes.CHECKCAST, "kotlinx/serialization/KSerializer"); nextIs(Opcodes.ARETURN); diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 71a5478aa9..932b31e4f0 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -51,7 +51,8 @@

    New Features

    composition is filtered out during generation of report (GitHub #1911).
  • Methods generated by the Kotlin serialization compiler plugin are filtered out - (GitHub #1885).
  • + (GitHub #1885, + #1970).

    Fixed bugs

    From de76181b207b18c5b727051f8d62c115dc2c976c Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com> Date: Sat, 11 Oct 2025 01:31:58 +0200 Subject: [PATCH 254/255] KotlinSerializableFilter should filter more methods (#1971) --- .../kotlin/KotlinSerializableEnumTest.java | 6 + .../kotlin/KotlinSerializableObjectTest.java | 33 ++++ .../kotlin/KotlinSerializableSealedTest.java | 16 ++ .../kotlin/KotlinSerializableTest.java | 9 ++ .../targets/KotlinSerializableEnumTarget.kt | 8 +- .../targets/KotlinSerializableObjectTarget.kt | 31 ++++ .../targets/KotlinSerializableSealedTarget.kt | 12 +- .../filter/KotlinSerializableFilterTest.java | 143 ++++++++++++++++-- .../filter/KotlinSerializableFilter.java | 53 +++++-- org.jacoco.doc/docroot/doc/changes.html | 3 +- 10 files changed, 276 insertions(+), 38 deletions(-) create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableObjectTest.java create mode 100644 org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableObjectTarget.kt diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java index bc2508690c..4b32bee0d2 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableEnumTest.java @@ -14,6 +14,7 @@ import org.jacoco.core.test.validation.ValidationTestBase; import org.jacoco.core.test.validation.kotlin.targets.KotlinSerializableEnumTarget; +import org.junit.Test; /** * Test of code coverage in {@link KotlinSerializableEnumTarget}. @@ -24,4 +25,9 @@ public KotlinSerializableEnumTest() { super(KotlinSerializableEnumTarget.class); } + @Test + public void test_method_count() { + assertMethodCount(/* main + static initializer */2); + } + } diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableObjectTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableObjectTest.java new file mode 100644 index 0000000000..5d42a805b2 --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableObjectTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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.KotlinSerializableObjectTarget; +import org.junit.Test; + +/** + * Test of code coverage in {@link KotlinSerializableObjectTarget}. + */ +public class KotlinSerializableObjectTest extends ValidationTestBase { + + public KotlinSerializableObjectTest() { + super(KotlinSerializableObjectTarget.class); + } + + @Test + public void test_method_count() { + assertMethodCount(/* main + static initializer */2); + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java index d225d9a374..a4374ca2d3 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableSealedTest.java @@ -12,8 +12,12 @@ *******************************************************************************/ package org.jacoco.core.test.validation.kotlin; +import java.util.Collection; +import java.util.Collections; + import org.jacoco.core.test.validation.ValidationTestBase; import org.jacoco.core.test.validation.kotlin.targets.KotlinSerializableSealedTarget; +import org.junit.Test; /** * Test of code coverage in {@link KotlinSerializableSealedTarget}. @@ -24,4 +28,16 @@ public KotlinSerializableSealedTest() { super(KotlinSerializableSealedTarget.class); } + @Override + protected Collection additionalClassesForAnalysis() { + return Collections.singletonList( + "org.jacoco.core.test.validation.kotlin.targets.KotlinSerializableSealedTarget$Sealed$A$$serializer"); + } + + @Test + public void test_method_count() { + assertMethodCount( + /* main + static initializer + constructor + getter */4); + } + } diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java index 1afc08cf5a..e6131254a6 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSerializableTest.java @@ -12,6 +12,9 @@ *******************************************************************************/ package org.jacoco.core.test.validation.kotlin; +import java.util.Collection; +import java.util.Collections; + import org.jacoco.core.test.validation.ValidationTestBase; import org.jacoco.core.test.validation.kotlin.targets.KotlinSerializableTarget; import org.junit.Test; @@ -25,6 +28,12 @@ public KotlinSerializableTest() { super(KotlinSerializableTarget.class); } + @Override + protected Collection additionalClassesForAnalysis() { + return Collections.singletonList( + "org.jacoco.core.test.validation.kotlin.targets.KotlinSerializableTarget$Example$$serializer"); + } + @Test public void test_method_count() { assertMethodCount( diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt index de3dae92a1..5cad0e605a 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableEnumTarget.kt @@ -19,10 +19,10 @@ import kotlinx.serialization.Serializable */ object KotlinSerializableEnumTarget { - @Serializable - enum class E { - V - } + @Serializable // assertFullyCovered() + enum class E { // assertEmpty() + V // assertFullyCovered() + } // assertFullyCovered() @JvmStatic fun main(args: Array) { diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableObjectTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableObjectTarget.kt new file mode 100644 index 0000000000..72effef81c --- /dev/null +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableObjectTarget.kt @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009, 2025 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 kotlinx.serialization.Serializable + +/** + * Test target with [Serializable] `object`. + */ +object KotlinSerializableObjectTarget { + + @Serializable // assertFullyCovered() + private object Example { // assertEmpty() + } // assertFullyCovered() + + @JvmStatic + fun main(args: Array) { + Example.toString() + } + +} diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt index 0e639ab198..ce04755339 100644 --- a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt +++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSerializableSealedTarget.kt @@ -19,11 +19,13 @@ import kotlinx.serialization.Serializable */ object KotlinSerializableSealedTarget { - @Serializable - private sealed class Sealed { - @Serializable - data class A(val data: String): Sealed() - } + @Serializable // assertFullyCovered() + private sealed class Sealed { // assertEmpty() + @Serializable // assertFullyCovered() + data class A( // assertFullyCovered() + val data: String // assertFullyCovered() + ): Sealed() // assertEmpty() + } // assertFullyCovered() @JvmStatic fun main(args: Array) { diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java index ab678e75cd..6e626511f0 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilterTest.java @@ -172,6 +172,15 @@ public void should_not_filter_hand_written_serializer_method() { } /** + * Example.serializer in case of + * + *
    +	 * @kotlinx.serialization.Serializable // line 1
    +	 * object Example
    +	 * 
    + * + * Example$Companion.serializer in case of + * *
     	 * @kotlinx.serialization.Serializable // line 1
     	 * enum class Example {
    @@ -181,20 +190,12 @@ public void should_not_filter_hand_written_serializer_method() {
     	 *
     	 * 
     	 * @kotlinx.serialization.Serializable // line 1
    -	 * sealed class Example {
    -	 * }
    +	 * sealed class Example
     	 * 
    */ @Test - public void should_filter_generated_serializer_method_in_companions_of_enum_and_sealed_class() { - context.className = "Example$Companion"; - - final MethodNode initMethod = new MethodNode(Opcodes.ACC_PRIVATE, - "", "()V", null, null); - final Label initMethodLineNumberLabel = new Label(); - initMethod.visitLabel(initMethodLineNumberLabel); - initMethod.visitLineNumber(1, initMethodLineNumberLabel); - filter.filter(initMethod, context, output); + public void should_filter_generated_serializer_method_in_objects_and_companions_of_enum_and_sealed_class() { + context.className = "Example"; final MethodNode m = new MethodNode( Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "serializer", @@ -204,15 +205,129 @@ public void should_filter_generated_serializer_method_in_companions_of_enum_and_ m.visitLabel(label0); m.visitLineNumber(1, label0); m.visitVarInsn(Opcodes.ALOAD, 0); - m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Example$Companion", + m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Example", "get$cachedSerializer", "()Lkotlinx/serialization/KSerializer;", false); m.visitInsn(Opcodes.ARETURN); filter.filter(m, context, output); - // FIXME https://github.com/jacoco/jacoco/issues/1971 - assertIgnored(m); + assertMethodIgnored(m); + } + + /** + * Example.get$cachedSerializer in case of + * + *
    +	 * @kotlinx.serialization.Serializable
    +	 * object Example
    +	 * 
    + * + * Example$Companion.get$cachedSerializer in case of + * + *
    +	 * @kotlinx.serialization.Serializable
    +	 * enum class Example {
    +	 *     V
    +	 * }
    +	 * 
    + * + *
    +	 * @kotlinx.serialization.Serializable
    +	 * sealed class Example
    +	 * 
    + */ + @Test + public void should_filter_synthetic_get_cachedSerializer_method() { + context.className = "Example"; + + MethodNode m = new MethodNode( + Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, + "get$cachedSerializer", "()Lkotlinx/serialization/KSerializer;", + null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
    +	 * @kotlinx.serialization.Serializable
    +	 * object Example
    +	 * 
    + * + *
    +	 * @kotlinx.serialization.Serializable
    +	 * enum class Example
    +	 * 
    + * + *
    +	 * @kotlinx.serialization.Serializable
    +	 * sealed class Example
    +	 * 
    + * + * lazy initializer + * + *
    +	 * $cachedSerializer$delegate = lazy { ... }
    +	 * 
    + * + * not executed when serializer is not used + * + * https://github.com/JetBrains/kotlin/commit/3f034e8b6735a50ed5733e82811fc2bdb73f5632 + */ + @Test + public void should_filter_synthetic_lazy_cachedSerializer() { + context.className = "Example"; + + final MethodNode m = new MethodNode( + Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC + | Opcodes.ACC_SYNTHETIC, + "_init_$_anonymous_", "()Lkotlinx/serialization/KSerializer;", + null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); + } + + /** + *
    +	 * @kotlinx.serialization.Serializable
    +	 * data class Example(
    +	 *     val data1: List<String>,
    +	 *     val data2: List<String>,
    +	 * )
    +	 * 
    + * + * lazy initializer + * + *
    +	 * $childSerializers = arrayOf(lazy { ... }, lazy { ... })
    +	 * 
    + * + * not executed when serializer is not used + * + * https://github.com/JetBrains/kotlin/commit/b35161e241df6a7b245b5a5d81232b0ea5a3129a + * https://github.com/JetBrains/kotlin/commit/3f034e8b6735a50ed5733e82811fc2bdb73f5632 + */ + @Test + public void should_filter_synthetic_lazy_childSerializers() { + context.className = "Example"; + + final MethodNode m = new MethodNode( + Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC + | Opcodes.ACC_SYNTHETIC, + "_childSerializers$_anonymous_$0", + "()Lkotlinx/serialization/KSerializer;", null, null); + m.visitInsn(Opcodes.NOP); + + filter.filter(m, context, output); + + assertMethodIgnored(m); } } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java index 87dc23accd..22d630d60f 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinSerializableFilter.java @@ -30,21 +30,25 @@ final class KotlinSerializableFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { - if (context.getClassName().endsWith("$Companion")) { - if (methodNode.name.equals("") - && methodNode.desc.equals("()V")) { - lineNumber = -1; - for (final AbstractInsnNode i : methodNode.instructions) { - if (i.getType() == AbstractInsnNode.LINE) { - lineNumber = ((LineNumberNode) i).line; - return; - } + if (context.getClassName().endsWith("$Companion") + && methodNode.name.equals("") + && methodNode.desc.equals("()V")) { + lineNumber = -1; + for (final AbstractInsnNode i : methodNode.instructions) { + if (i.getType() == AbstractInsnNode.LINE) { + lineNumber = ((LineNumberNode) i).line; + return; } } - if (methodNode.name.equals("serializer") - && methodNode.desc - .equals("()Lkotlinx/serialization/KSerializer;") - && new Matcher().match(methodNode, lineNumber)) { + return; + } + + if (methodNode.name.equals("serializer") && methodNode.desc + .equals("()Lkotlinx/serialization/KSerializer;")) { + final Matcher matcher = new Matcher(); + if (matcher.matchSerializer(methodNode, lineNumber) + || matcher.matchCachedSerializer(methodNode, + context.getClassName())) { output.ignore(methodNode.instructions.getFirst(), methodNode.instructions.getLast()); } @@ -61,6 +65,17 @@ && new Matcher().match(methodNode, lineNumber)) { return; } + if ((methodNode.name.equals("get$cachedSerializer") + // https://github.com/JetBrains/kotlin/blob/v2.2.20/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrBuilderWithPluginContext.kt#L61 + || methodNode.name.startsWith("_init_$_anonymous_") + || methodNode.name.startsWith("_childSerializers$_anonymous_")) + && methodNode.desc + .equals("()Lkotlinx/serialization/KSerializer;")) { + output.ignore(methodNode.instructions.getFirst(), + methodNode.instructions.getLast()); + return; + } + final Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc); if (argumentTypes.length > 1 && argumentTypes[argumentTypes.length - 1] .getClassName() @@ -71,7 +86,7 @@ && new Matcher().match(methodNode, lineNumber)) { } private static class Matcher extends AbstractMatcher { - public boolean match(final MethodNode methodNode, + public boolean matchSerializer(final MethodNode methodNode, final int lineNumber) { cursor = methodNode.instructions.getFirst(); nextIs(Opcodes.GETSTATIC); @@ -88,6 +103,16 @@ public boolean match(final MethodNode methodNode, && (lineNumber == -1 || lineNumber == ((LineNumberNode) lineNumberInstruction).line); } + + private boolean matchCachedSerializer(final MethodNode methodNode, + final String className) { + firstIsALoad0(methodNode); + nextIsInvoke(Opcodes.INVOKESPECIAL, className, + "get$cachedSerializer", + "()Lkotlinx/serialization/KSerializer;"); + nextIs(Opcodes.ARETURN); + return cursor != null; + } } } diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 932b31e4f0..2fcbd3b637 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -52,7 +52,8 @@

    New Features

    (GitHub #1911).
  • Methods generated by the Kotlin serialization compiler plugin are filtered out (GitHub #1885, - #1970).
  • + #1970, + #1971).

    Fixed bugs

    From 2eb248366f0eb63fd964fc7a81804b27229a6edd Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sat, 11 Oct 2025 02:24:29 +0200 Subject: [PATCH 255/255] Prepare release v0.8.14 --- jacoco-maven-plugin.test/pom.xml | 2 +- jacoco-maven-plugin/pom.xml | 2 +- jacoco/pom.xml | 2 +- org.jacoco.agent.rt.test/pom.xml | 2 +- org.jacoco.agent.rt/pom.xml | 2 +- org.jacoco.agent.test/pom.xml | 2 +- org.jacoco.agent/pom.xml | 2 +- org.jacoco.ant.test/pom.xml | 2 +- org.jacoco.ant/pom.xml | 2 +- org.jacoco.build/pom.xml | 2 +- org.jacoco.cli.test/pom.xml | 2 +- org.jacoco.cli/pom.xml | 2 +- org.jacoco.core.test.validation.groovy/pom.xml | 2 +- org.jacoco.core.test.validation.java14/pom.xml | 2 +- org.jacoco.core.test.validation.java16/pom.xml | 2 +- org.jacoco.core.test.validation.java21/pom.xml | 2 +- org.jacoco.core.test.validation.java5/pom.xml | 2 +- org.jacoco.core.test.validation.java7/pom.xml | 2 +- org.jacoco.core.test.validation.java8/pom.xml | 2 +- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- org.jacoco.core.test.validation.scala/pom.xml | 2 +- org.jacoco.core.test.validation/pom.xml | 2 +- org.jacoco.core.test/pom.xml | 2 +- org.jacoco.core/pom.xml | 2 +- org.jacoco.doc/docroot/doc/changes.html | 2 +- org.jacoco.doc/pom.xml | 2 +- org.jacoco.examples.test/pom.xml | 2 +- org.jacoco.examples/pom.xml | 2 +- org.jacoco.report.test/pom.xml | 2 +- org.jacoco.report/pom.xml | 2 +- org.jacoco.tests/pom.xml | 2 +- pom.xml | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml index 7d55c48a84..a7aab39c67 100644 --- a/jacoco-maven-plugin.test/pom.xml +++ b/jacoco-maven-plugin.test/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml index 9345168453..47756fddfe 100644 --- a/jacoco-maven-plugin/pom.xml +++ b/jacoco-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/jacoco/pom.xml b/jacoco/pom.xml index 0df00081a1..5d5b84fae1 100644 --- a/jacoco/pom.xml +++ b/jacoco/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml index b7a42e0a0b..aa6770215a 100644 --- a/org.jacoco.agent.rt.test/pom.xml +++ b/org.jacoco.agent.rt.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml index ed0040a0b4..74502c3732 100644 --- a/org.jacoco.agent.rt/pom.xml +++ b/org.jacoco.agent.rt/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml index 3e4844a0ee..759b67b527 100644 --- a/org.jacoco.agent.test/pom.xml +++ b/org.jacoco.agent.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml index dcde39c139..2db4835c35 100644 --- a/org.jacoco.agent/pom.xml +++ b/org.jacoco.agent/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml index 88d87298b5..36beb4b74c 100644 --- a/org.jacoco.ant.test/pom.xml +++ b/org.jacoco.ant.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml index 1ad7cb4f90..0913762486 100644 --- a/org.jacoco.ant/pom.xml +++ b/org.jacoco.ant/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml index 81c6d48afb..8254b3cfb0 100644 --- a/org.jacoco.build/pom.xml +++ b/org.jacoco.build/pom.xml @@ -15,7 +15,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 pom JaCoCo diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml index d6b2ebb5cf..6243516031 100644 --- a/org.jacoco.cli.test/pom.xml +++ b/org.jacoco.cli.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml index fb031f26be..15a7c1cee7 100644 --- a/org.jacoco.cli/pom.xml +++ b/org.jacoco.cli/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml index b759cdf288..372744313e 100644 --- a/org.jacoco.core.test.validation.groovy/pom.xml +++ b/org.jacoco.core.test.validation.groovy/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java14/pom.xml b/org.jacoco.core.test.validation.java14/pom.xml index 313c9f5a54..9dd3da4dfd 100644 --- a/org.jacoco.core.test.validation.java14/pom.xml +++ b/org.jacoco.core.test.validation.java14/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java16/pom.xml b/org.jacoco.core.test.validation.java16/pom.xml index 1917fd753a..6dfd9c4edf 100644 --- a/org.jacoco.core.test.validation.java16/pom.xml +++ b/org.jacoco.core.test.validation.java16/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java21/pom.xml b/org.jacoco.core.test.validation.java21/pom.xml index 44f4e83cea..38e887a30b 100644 --- a/org.jacoco.core.test.validation.java21/pom.xml +++ b/org.jacoco.core.test.validation.java21/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml index f451de7ffd..f2c9f2f587 100644 --- a/org.jacoco.core.test.validation.java5/pom.xml +++ b/org.jacoco.core.test.validation.java5/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml index 38618add59..1e6f503587 100644 --- a/org.jacoco.core.test.validation.java7/pom.xml +++ b/org.jacoco.core.test.validation.java7/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml index 3f0ba85e56..14816d8140 100644 --- a/org.jacoco.core.test.validation.java8/pom.xml +++ b/org.jacoco.core.test.validation.java8/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 2713203166..b5ca3f9743 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation.scala/pom.xml b/org.jacoco.core.test.validation.scala/pom.xml index d3183cbf36..391f4bada0 100644 --- a/org.jacoco.core.test.validation.scala/pom.xml +++ b/org.jacoco.core.test.validation.scala/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.core.test.validation - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.core.test.validation diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml index c4b2d85bca..74259f1dab 100644 --- a/org.jacoco.core.test.validation/pom.xml +++ b/org.jacoco.core.test.validation/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml index 75e00a37f0..769fe8ea66 100644 --- a/org.jacoco.core.test/pom.xml +++ b/org.jacoco.core.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml index e9d0b72edd..b09b0e85d0 100644 --- a/org.jacoco.core/pom.xml +++ b/org.jacoco.core/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 2fcbd3b637..30bf30be2c 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -18,7 +18,7 @@

    Change History

    -

    Snapshot Build @qualified.bundle.version@ (@build.date@)

    +

    Release 0.8.14 (2025/10/11)

    New Features

      diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml index 9b7f013ae3..9114022baa 100644 --- a/org.jacoco.doc/pom.xml +++ b/org.jacoco.doc/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml index 826f2275da..2f12e2a61b 100644 --- a/org.jacoco.examples.test/pom.xml +++ b/org.jacoco.examples.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml index 93116051b9..5edddab16a 100644 --- a/org.jacoco.examples/pom.xml +++ b/org.jacoco.examples/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml index 36f16a66e7..8af6fcd482 100644 --- a/org.jacoco.report.test/pom.xml +++ b/org.jacoco.report.test/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.tests - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.tests diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml index 908fd630e3..511e2c90c5 100644 --- a/org.jacoco.report/pom.xml +++ b/org.jacoco.report/pom.xml @@ -16,7 +16,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml index dc3666b932..6f9d5391c8 100644 --- a/org.jacoco.tests/pom.xml +++ b/org.jacoco.tests/pom.xml @@ -17,7 +17,7 @@ org.jacoco org.jacoco.build - 0.8.14-SNAPSHOT + 0.8.14 ../org.jacoco.build diff --git a/pom.xml b/pom.xml index eb9d68c508..4907865387 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jacoco root - 0.8.14-SNAPSHOT + 0.8.14 pom