Scripting: code coverage

Added a way to collect code coverage from scripting autotest in isolation

^OSIP-1298
diff --git a/compiler/test-coverage/scripting/build.gradle.kts b/compiler/test-coverage/scripting/build.gradle.kts
new file mode 100644
index 0000000..c824961
--- /dev/null
+++ b/compiler/test-coverage/scripting/build.gradle.kts
@@ -0,0 +1,214 @@
+import org.gradle.api.tasks.SourceSetContainer
+import org.gradle.api.tasks.testing.Test
+import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
+import org.gradle.testing.jacoco.tasks.JacocoReport
+
+plugins {
+    id("base")
+    id("jacoco")
+}
+
+description = "Aggregated JaCoCo coverage for compiler code exercised by Kotlin scripting tests"
+
+jacoco {
+    toolVersion = libs.versions.jacoco.get()
+}
+
+val scriptingTestProjects = listOf(
+    ":plugins:scripting:scripting-tests",
+    ":kotlin-scripting-common",
+    ":kotlin-scripting-jvm",
+    ":kotlin-scripting-jvm-host-test",
+    ":kotlin-scripting-dependencies",
+    ":kotlin-scripting-dependencies-maven",
+    ":kotlin-scripting-jsr223-test",
+    ":kotlin-main-kts",
+    ":kotlin-main-kts-test",
+    ":examples:scripting-jvm-simple-script-host",
+    ":examples:scripting-jvm-maven-deps-host",
+    ":examples:scripting-jvm-embeddable-host",
+    ":examples:scripting-jsr223-daemon",
+    ":examples:scripting-jsr223-bta",
+)
+
+// These projects use Kotlin's custom projectTests/Test tasks rather than published
+// JVM-test-suite coverage variants. Evaluate them first so the task collection below
+// sees every custom Test task, then apply JaCoCo directly and consume each task's
+// configured destination file instead of relying on jacocoAggregation resolution.
+scriptingTestProjects.forEach { evaluationDependsOn(it) }
+
+val scriptingExecutionData = objects.fileCollection()
+scriptingTestProjects.forEach { path ->
+    val producer = project(path)
+    producer.pluginManager.apply("jacoco")
+    producer.tasks.withType<Test>().configureEach {
+        extensions.configure<JacocoTaskExtension> {
+            isEnabled = true
+            scriptingExecutionData.from(destinationFile)
+        }
+    }
+}
+
+
+// Class/source providers: these are report inputs only, never execution-data producers.
+val reportClassScopeProjects = listOf(
+    // The compiler-side scripting implementation is here, not in scripting-tests.
+    ":kotlin-scripting-compiler",
+    ":kotlin-scripting-compiler-impl",
+    ":kotlin-scripting-common",
+    ":kotlin-scripting-jvm",
+    ":kotlin-scripting-dependencies",
+    ":kotlin-scripting-dependencies-maven",
+    ":kotlin-main-kts",
+    ":examples:scripting-jvm-simple-script-host",
+    ":examples:scripting-jvm-maven-deps-host",
+    ":examples:scripting-jvm-embeddable-host",
+    ":examples:scripting-jsr223-daemon",
+    ":examples:scripting-jsr223-bta",
+    ":compiler",
+    ":compiler:util",
+    ":compiler:config",
+    ":compiler:config.jvm",
+    ":compiler:arguments.common",
+    ":compiler:arguments",
+    ":compiler:container",
+    ":compiler:resolution.common",
+    ":compiler:resolution.common.js",
+    ":compiler:resolution.common.jvm",
+    ":compiler:resolution",
+    ":compiler:serialization.common",
+    ":compiler:serialization",
+    ":compiler:psi:psi-api",
+    ":compiler:psi:psi-impl",
+    ":compiler:psi:psi-utils",
+    ":compiler:psi:psi-frontend-utils",
+    ":compiler:psi:parser",
+    ":compiler:multiplatform-parsing",
+    ":compiler:frontend",
+    ":compiler:frontend.common",
+    ":compiler:frontend.common-psi",
+    ":compiler:frontend.java",
+    ":compiler:frontend.common.jvm",
+    ":compiler:frontend:cfg",
+    ":compiler:ir.tree",
+    ":compiler:ir.psi2ir",
+    ":compiler:ir.objcinterop",
+    ":compiler:ir.backend.common",
+    ":compiler:ir.backend.native",
+    ":compiler:ir.actualization",
+    ":compiler:ir.serialization.common",
+    ":compiler:ir.serialization.jvm",
+    ":compiler:ir.serialization.js",
+    ":compiler:ir.serialization.native",
+    ":compiler:ir.serialization.jklib",
+    ":compiler:ir.inline",
+    ":compiler:ir.validation",
+    ":compiler:backend",
+    ":compiler:backend.common.jvm",
+    ":compiler:backend.jvm",
+    ":compiler:backend.jvm.lower",
+    ":compiler:backend.jvm.codegen",
+    ":compiler:backend.jvm.entrypoint",
+    ":compiler:backend.js",
+    ":compiler:backend.wasm",
+    ":compiler:plugin-api",
+    ":compiler:java-direct",
+    ":compiler:cli-base",
+    ":compiler:cli",
+    ":compiler:cli-jvm",
+    ":compiler:cli-js",
+    ":compiler:cli-jklib",
+    ":compiler:cli-metadata",
+    ":compiler:cli:cli-native-klib",
+    ":compiler:incremental-compilation-impl",
+    ":compiler:fir:cones",
+    ":compiler:fir:tree",
+    ":compiler:fir:semantics.api",
+    ":compiler:fir:resolve",
+    ":compiler:fir:plugin.api",
+    ":compiler:fir:fir-serialization",
+    ":compiler:fir:fir-deserialization",
+    ":compiler:fir:fir-jvm",
+    ":compiler:fir:fir-native",
+    ":compiler:fir:checkers:checkers.api",
+    ":compiler:fir:checkers:checkers.common",
+    ":compiler:fir:checkers:checkers.jvm",
+    ":compiler:fir:checkers:checkers.js",
+    ":compiler:fir:checkers:checkers.native",
+    ":compiler:fir:checkers:checkers.wasm",
+    ":compiler:fir:checkers:checkers.web.common",
+    ":compiler:fir:diagnostic-renderers",
+    ":compiler:fir:entrypoint",
+    ":compiler:fir:raw-fir:raw-fir.common",
+    ":compiler:fir:fir2ir",
+    ":compiler:fir:fir2ir:jvm-backend",
+    ":core:names",
+    ":core:language.model",
+    ":core:language.targets",
+    ":core:language.targets.jvm",
+    ":core:language.version-settings",
+    ":core:compiler.common",
+    ":core:compiler.common.jvm",
+    ":core:compiler.common.js",
+    ":core:compiler.common.native",
+    ":core:compiler.common.wasm",
+    ":core:compiler.common.web",
+    ":core:descriptors",
+    ":core:descriptors.jvm",
+    ":core:deserialization",
+    ":core:deserialization.common",
+    ":core:deserialization.common.jvm",
+    ":core:descriptors.runtime",
+    ":core:metadata",
+    ":core:metadata.jvm",
+    ":core:util.runtime",
+)
+
+val reportJvmClassScopeProjects = reportClassScopeProjects.filter { path ->
+    val candidate = project(path)
+    candidate.extensions.findByType<SourceSetContainer>()?.findByName("main") != null &&
+        candidate.tasks.findByName("classes") != null
+}
+
+val reportClassDirectories = objects.fileCollection()
+val reportSourceDirectories = objects.fileCollection()
+
+reportJvmClassScopeProjects.forEach { path ->
+    val mainSourceSet = project(path).extensions.getByType<SourceSetContainer>().findByName("main")!!
+    reportClassDirectories.from(mainSourceSet.output.classesDirs)
+    reportSourceDirectories.from(mainSourceSet.allSource.srcDirs)
+}
+
+tasks.register<JacocoReport>("scriptingCoverageReport") {
+    group = "verification"
+    description = "Generates compiler-wide coverage from scripting tests only"
+
+    // Run every scripting producer before evaluating the report's built-in
+    // "any execution data exists" predicate.
+    scriptingTestProjects.forEach { path ->
+        dependsOn(project(path).tasks.withType<Test>())
+    }
+    executionData.setFrom(scriptingExecutionData)
+
+    // Build class-only inputs. Test projects contribute execution data only.
+    dependsOn(reportJvmClassScopeProjects.map { "$it:classes" })
+    classDirectories.setFrom(
+        reportClassDirectories.asFileTree.matching {
+            include(
+                // Compiler/plugin-side scripting implementation and JSR-223 integration.
+                "org/jetbrains/kotlin/**",
+                // Public scripting API/host implementations use this package root.
+                "kotlin/script/experimental/**"
+            )
+            exclude("org/jetbrains/kotlin/util/vavr/VavrAdaptersKt.class")
+        }
+    )
+    sourceDirectories.setFrom(reportSourceDirectories)
+
+    reports {
+        html.required = true
+        xml.required = true
+        csv.required = false
+    }
+
+}
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index e63ed36..310070c 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -2622,11 +2622,21 @@
             <sha256 value="20be9853385bdfc65a5929643412d09243d14514304b89ba23a265158cc8792b" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jacoco" name="org.jacoco.agent" version="0.8.15">
+         <artifact name="org.jacoco.agent-0.8.15.jar">
+            <sha256 value="81607adaa5b03a687a04049dee6b07e9665708c3e6f7b0626892ca9659be587c" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.jacoco" name="org.jacoco.ant" version="0.8.14">
          <artifact name="org.jacoco.ant-0.8.14.jar">
             <sha256 value="9fff68954d5de3aad2bf838eaf886ed67d2c22a2d6c6f095548bade8c45caeae" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jacoco" name="org.jacoco.ant" version="0.8.15">
+         <artifact name="org.jacoco.ant-0.8.15.jar">
+            <sha256 value="54fb6af97c95352d7deeb49113d7ad63f190eaa8cc9ae8e068fdb2f2a6de009e" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.jacoco" name="org.jacoco.cli" version="0.8.14">
          <artifact name="org.jacoco.cli-0.8.14.jar">
             <sha256 value="12d5d78351c638efeea71ac840f6a5cf7bcff89001ddb05eb89f956d1079a2c6" origin="Generated by Gradle"/>
@@ -2637,11 +2647,21 @@
             <sha256 value="28abbf0eea5a08e4f24097f2fbac663ca17c341c25c3a04d90d6cd325943c995" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jacoco" name="org.jacoco.core" version="0.8.15">
+         <artifact name="org.jacoco.core-0.8.15.jar">
+            <sha256 value="ade1e0fdb4cd80d8537b57c6edb70a1360c47fdc518c20c65314517479bc4d0d" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.jacoco" name="org.jacoco.report" version="0.8.14">
          <artifact name="org.jacoco.report-0.8.14.jar">
             <sha256 value="a3e2026060ab8b8d5c650706406234bb4c033dfd5376afeb8b1666e8ed27c453" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jacoco" name="org.jacoco.report" version="0.8.15">
+         <artifact name="org.jacoco.report-0.8.15.jar">
+            <sha256 value="66a79e36edc77a1ebf6689e76a976e12ab4f1af515cbd09555840fba775714f4" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.javassist" name="javassist" version="3.28.0-GA">
          <artifact name="javassist-3.28.0-GA.jar">
             <sha256 value="57d0a9e9286f82f4eaa851125186997f811befce0e2060ff0a15a77f5a9dd9a7" origin="Generated by Gradle"/>
@@ -4885,6 +4905,11 @@
             <sha256 value="0df97574914aee92fd349d0cb4e00f3345d45b2c239e0bb50f0a90ead47888e0" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.ow2.asm" name="asm" version="9.10.1">
+         <artifact name="asm-9.10.1.jar">
+            <sha256 value="ed825d10ab1399c8c0cb669e688cf0c8c82629b4c8399b58352b68e92ca10fcb" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.ow2.asm" name="asm" version="9.2">
          <artifact name="asm-9.2.jar">
             <sha256 value="b9d4fe4d71938df38839f0eca42aaaa64cf8b313d678da036f0cb3ca199b47f5" origin="Generated by Gradle"/>
@@ -4925,6 +4950,11 @@
             <sha256 value="6a15d28e8bd29ba4fd5bca4baf9b50e8fba2d7b51fbf78cfa0c875a7214c678b" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.ow2.asm" name="asm-commons" version="9.10.1">
+         <artifact name="asm-commons-9.10.1.jar">
+            <sha256 value="6d0abefb7cbf972ea16edb37ec14835372505063a45f976ab7ea889ed9497895" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.ow2.asm" name="asm-commons" version="9.6">
          <artifact name="asm-commons-9.6.jar">
             <sha256 value="7aefd0d5c0901701c69f7513feda765fb6be33af2ce7aa17c5781fc87657c511" origin="Generated by Gradle"/>
@@ -4940,6 +4970,11 @@
             <sha256 value="db2f6f26150bbe7c126606b4a1151836bcc22a1e05a423b3585698bece995ff8" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.ow2.asm" name="asm-tree" version="9.10.1">
+         <artifact name="asm-tree-9.10.1.jar">
+            <sha256 value="3dfb0d5b6a106cd40b5b250e39935fbf2f927f4477546a5369a3ac609cf0506b" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.ow2.asm" name="asm-tree" version="9.6">
          <artifact name="asm-tree-9.6.jar">
             <sha256 value="c43ecf17b539c777e15da7b5b86553b377e2d39a683de6285567d5283888e7ef" origin="Generated by Gradle"/>
diff --git a/libraries/tools/kotlin-main-kts-test/build.gradle.kts b/libraries/tools/kotlin-main-kts-test/build.gradle.kts
index 093256f..154ef06 100644
--- a/libraries/tools/kotlin-main-kts-test/build.gradle.kts
+++ b/libraries/tools/kotlin-main-kts-test/build.gradle.kts
@@ -36,7 +36,7 @@
 }
 
 projectTests {
-    testTask {
+    testTask(javaLauncher = JdkMajorVersion.JDK_17_0) {
         dependsOn(":dist", ":kotlinx-serialization-compiler-plugin.embeddable:embeddable")
         workingDir = rootDir
         val localKotlinxSerializationPluginClasspath: FileCollection = kotlinxSerializationGradlePluginClasspath
diff --git a/plugins/scripting/scripting-tests/build.gradle.kts b/plugins/scripting/scripting-tests/build.gradle.kts
index dcec92a..739c0a9 100644
--- a/plugins/scripting/scripting-tests/build.gradle.kts
+++ b/plugins/scripting/scripting-tests/build.gradle.kts
@@ -58,6 +58,11 @@
         )
     ) {
         workingDir = rootDir
+        // `kotlinc` launcher script started by the tests must run on JDK 17+
+        val jdkHome = project.getToolchainJdkHomeFor(JdkMajorVersion.JDK_17_0)
+        doFirst {
+            environment("JAVA_HOME", jdkHome.get())
+        }
         addClasspathProperty(testSourceSet.output.classesDirs, "kotlin.test.script.classpath")
         addClasspathProperty(powerAssertCompilerPluginJar, "kotlin.power.assert.compiler.plugin.jar")
         addClasspathProperty(kotlinxSerializationGradlePluginClasspath, "kotlin.script.test.kotlinx.serialization.plugin.classpath")
diff --git a/settings.gradle.kts b/settings.gradle.kts
index d9095c8..b62b4fa 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -547,6 +547,7 @@
 
 include(
     ":compiler:test-coverage",
+    ":compiler:test-coverage:scripting",
     ":compiler:test-infrastructure",
     ":compiler:test-infrastructure:grouping-test-engine",
     ":compiler:test-infrastructure-utils",