From 2570be129f3a875f7b3d7402980f4ee26de87e17 Mon Sep 17 00:00:00 2001 From: "Alexander.Likhachev" Date: Thu, 17 Aug 2023 13:46:19 +0200 Subject: [PATCH] [Gradle, BT] Move script definitions scanning into the build tools API #KT-61449 In Progress --- .../api/kotlin-build-tools-api.api | 1 + .../buildtools/api/CompilationService.kt | 8 ++ .../kotlin-build-tools-impl/build.gradle.kts | 3 + .../internal/CompilationServiceImpl.kt | 15 ++++ .../kotlin-gradle-plugin/build.gradle.kts | 3 - .../internal/ScriptingGradleSubplugin.kt | 78 +++++++++++-------- .../kotlin-build-tools-impl.pom | 12 +++ .../kotlin-gradle-plugin.pom | 64 --------------- 8 files changed, 83 insertions(+), 101 deletions(-) diff --git a/compiler/build-tools/kotlin-build-tools-api/api/kotlin-build-tools-api.api b/compiler/build-tools/kotlin-build-tools-api/api/kotlin-build-tools-api.api index b3861d4b30a..93b058004c7 100644 --- a/compiler/build-tools/kotlin-build-tools-api/api/kotlin-build-tools-api.api +++ b/compiler/build-tools/kotlin-build-tools-api/api/kotlin-build-tools-api.api @@ -12,6 +12,7 @@ public abstract interface class org/jetbrains/kotlin/buildtools/api/CompilationS public abstract fun calculateClasspathSnapshot (Ljava/io/File;Lorg/jetbrains/kotlin/buildtools/api/jvm/ClassSnapshotGranularity;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathEntrySnapshot; public abstract fun compileJvm (Lorg/jetbrains/kotlin/buildtools/api/ProjectId;Lorg/jetbrains/kotlin/buildtools/api/CompilerExecutionStrategyConfiguration;Lorg/jetbrains/kotlin/buildtools/api/jvm/JvmCompilationConfiguration;Ljava/util/List;Ljava/util/List;)Lorg/jetbrains/kotlin/buildtools/api/CompilationResult; public abstract fun finishProjectCompilation (Lorg/jetbrains/kotlin/buildtools/api/ProjectId;)V + public abstract fun getCustomKotlinScriptFilenameExtensions (Ljava/util/List;)Ljava/util/Collection; public static fun loadImplementation (Ljava/lang/ClassLoader;)Lorg/jetbrains/kotlin/buildtools/api/CompilationService; public abstract fun makeCompilerExecutionStrategyConfiguration ()Lorg/jetbrains/kotlin/buildtools/api/CompilerExecutionStrategyConfiguration; public abstract fun makeJvmCompilationConfiguration ()Lorg/jetbrains/kotlin/buildtools/api/jvm/JvmCompilationConfiguration; diff --git a/compiler/build-tools/kotlin-build-tools-api/src/main/kotlin/org/jetbrains/kotlin/buildtools/api/CompilationService.kt b/compiler/build-tools/kotlin-build-tools-api/src/main/kotlin/org/jetbrains/kotlin/buildtools/api/CompilationService.kt index 11b86ea4df2..9238b92d571 100644 --- a/compiler/build-tools/kotlin-build-tools-api/src/main/kotlin/org/jetbrains/kotlin/buildtools/api/CompilationService.kt +++ b/compiler/build-tools/kotlin-build-tools-api/src/main/kotlin/org/jetbrains/kotlin/buildtools/api/CompilationService.kt @@ -70,6 +70,14 @@ public interface CompilationService { */ public fun finishProjectCompilation(projectId: ProjectId) + /** + * Retrieves the custom Kotlin script filename extensions based on script definitions from the specified classpath. + * + * @param classpath The list of files representing the classpath. + * @return A collection of strings representing the custom Kotlin script filename extensions. + */ + public fun getCustomKotlinScriptFilenameExtensions(classpath: List): Collection + @ExperimentalBuildToolsApi public companion object { @JvmStatic diff --git a/compiler/build-tools/kotlin-build-tools-impl/build.gradle.kts b/compiler/build-tools/kotlin-build-tools-impl/build.gradle.kts index c06ebadd866..caea856e024 100644 --- a/compiler/build-tools/kotlin-build-tools-impl/build.gradle.kts +++ b/compiler/build-tools/kotlin-build-tools-impl/build.gradle.kts @@ -14,8 +14,11 @@ dependencies { compileOnly(project(":compiler:incremental-compilation-impl")) compileOnly(project(":kotlin-compiler-runner-unshaded")) compileOnly(intellijCore()) + compileOnly(project(":kotlin-scripting-compiler")) runtimeOnly(project(":kotlin-compiler-embeddable")) runtimeOnly(project(":kotlin-compiler-runner")) + runtimeOnly(project(":kotlin-scripting-compiler-embeddable")) + runtimeOnly(project(":kotlin-scripting-compiler-impl-embeddable")) } publish() diff --git a/compiler/build-tools/kotlin-build-tools-impl/src/main/kotlin/org/jetbrains/kotlin/buildtools/internal/CompilationServiceImpl.kt b/compiler/build-tools/kotlin-build-tools-impl/src/main/kotlin/org/jetbrains/kotlin/buildtools/internal/CompilationServiceImpl.kt index fc20a28138a..c17cda7c60f 100644 --- a/compiler/build-tools/kotlin-build-tools-impl/src/main/kotlin/org/jetbrains/kotlin/buildtools/internal/CompilationServiceImpl.kt +++ b/compiler/build-tools/kotlin-build-tools-impl/src/main/kotlin/org/jetbrains/kotlin/buildtools/internal/CompilationServiceImpl.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments import org.jetbrains.kotlin.cli.common.arguments.validateArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageRenderer +import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunnerUtils import org.jetbrains.kotlin.config.Services @@ -20,9 +22,12 @@ import org.jetbrains.kotlin.daemon.common.CompilerId import org.jetbrains.kotlin.daemon.common.configureDaemonJVMOptions import org.jetbrains.kotlin.daemon.common.filterExtractProps import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathEntrySnapshotter +import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter +import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource import java.io.File import java.net.URLClassLoader import java.util.concurrent.ConcurrentHashMap +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration private val ExitCode.asCompilationResult get() = when (this) { @@ -77,6 +82,16 @@ internal object CompilationServiceImpl : CompilationService { file.delete() } + override fun getCustomKotlinScriptFilenameExtensions(classpath: List): Collection { + val definitions = ScriptDefinitionsFromClasspathDiscoverySource( + classpath, + defaultJvmScriptingHostConfiguration, + PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter + ).definitions + + return definitions.mapTo(arrayListOf()) { it.fileExtension } + } + private fun compileInProcess( loggerAdapter: KotlinLoggerMessageCollectorAdapter, sources: List, diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts index d11ad3509ab..fc3d9ec4487 100644 --- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts @@ -66,7 +66,6 @@ dependencies { commonCompileOnly(project(":kotlin-daemon-client")) commonCompileOnly(project(":kotlin-gradle-compiler-types")) commonCompileOnly(project(":kotlin-compiler-runner-unshaded")) - commonCompileOnly(project(":kotlin-scripting-compiler")) commonCompileOnly(project(":kotlin-gradle-statistics")) commonCompileOnly(project(":kotlin-gradle-build-metrics")) commonCompileOnly("com.android.tools.build:gradle:4.2.2") { @@ -111,8 +110,6 @@ dependencies { exclude(group = "org.jetbrains.kotlin", module = "kotlin-build-common") exclude(group = "org.jetbrains.kotlin", module = "kotlin-compiler-embeddable") } - commonRuntimeOnly(project(":kotlin-scripting-compiler-embeddable")) - commonRuntimeOnly(project(":kotlin-scripting-compiler-impl-embeddable")) commonRuntimeOnly(project(":kotlin-util-klib")) commonRuntimeOnly(project(":prepare:kotlin-gradle-plugin-compiler-dependencies")) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt index 1365c715ff4..4864d55540e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt @@ -7,33 +7,31 @@ package org.jetbrains.kotlin.gradle.scripting.internal +import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.dsl.DependencyHandler -import org.gradle.api.artifacts.transform.CacheableTransform -import org.gradle.api.artifacts.transform.InputArtifact -import org.gradle.api.artifacts.transform.TransformAction -import org.gradle.api.artifacts.transform.TransformOutputs -import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.artifacts.transform.* import org.gradle.api.attributes.Attribute +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Internal import org.gradle.work.NormalizeLineEndings -import org.jetbrains.kotlin.cli.common.messages.MessageRenderer -import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector +import org.jetbrains.kotlin.buildtools.api.CompilationService +import org.jetbrains.kotlin.compilerRunner.btapi.SharedApiClassesClassLoaderProvider import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull +import org.jetbrains.kotlin.gradle.internal.ClassLoadersCachingBuildService import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeCompilation import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter -import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly -import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration private const val SCRIPTING_LOG_PREFIX = "kotlin scripting plugin:" @@ -114,11 +112,21 @@ private fun configureDiscoveryTransformation( attributes.attribute(artifactType, scriptFilesExtensions) extendsFrom(discoveryConfiguration) } - project.dependencies.registerOnceDiscoverScriptExtensionsTransform() + val classLoadersCachingService = ClassLoadersCachingBuildService.registerIfAbsent(project) + val compilerClasspath = project.configurations.named(BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME) + project.dependencies.registerOnceDiscoverScriptExtensionsTransform(classLoadersCachingService, compilerClasspath) } @CacheableTransform -internal abstract class DiscoverScriptExtensionsTransformAction : TransformAction { +internal abstract class DiscoverScriptExtensionsTransformAction : TransformAction { + interface Parameters : TransformParameters { + @get:Internal + val classLoadersCachingService: Property + + @get:Classpath + val compilerClasspath: ConfigurableFileCollection + } + @get:Classpath @get:InputArtifact @get:NormalizeLineEndings @@ -127,14 +135,11 @@ internal abstract class DiscoverScriptExtensionsTransformAction : TransformActio override fun transform(outputs: TransformOutputs) { val input = inputArtifact.get().asFile - val definitions = - ScriptDefinitionsFromClasspathDiscoverySource( - listOf(input), - defaultJvmScriptingHostConfiguration, - PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter - ).definitions + val classLoader = parameters.classLoadersCachingService.get() + .getClassLoader(parameters.compilerClasspath.toList(), SharedApiClassesClassLoaderProvider) + val compilationService = CompilationService.loadImplementation(classLoader) - val extensions = definitions.mapTo(arrayListOf()) { it.fileExtension } + val extensions = compilationService.getCustomKotlinScriptFilenameExtensions(listOf(input)) if (extensions.isNotEmpty()) { val outputFile = outputs.file("${input.nameWithoutExtension}.discoveredScriptsExtensions.txt") @@ -143,21 +148,33 @@ internal abstract class DiscoverScriptExtensionsTransformAction : TransformActio } } -private fun DependencyHandler.registerDiscoverScriptExtensionsTransform() { +private fun DependencyHandler.registerDiscoverScriptExtensionsTransform( + classLoadersCachingService: Provider, + compilerClasspath: NamedDomainObjectProvider, +) { + fun TransformSpec.configureCommonParameters() { + parameters.classLoadersCachingService.set(classLoadersCachingService) + parameters.compilerClasspath.from(compilerClasspath) + } registerTransform(DiscoverScriptExtensionsTransformAction::class.java) { transformSpec -> transformSpec.from.attribute(artifactType, "jar") transformSpec.to.attribute(artifactType, scriptFilesExtensions) + transformSpec.configureCommonParameters() } registerTransform(DiscoverScriptExtensionsTransformAction::class.java) { transformSpec -> transformSpec.from.attribute(artifactType, "classes") transformSpec.to.attribute(artifactType, scriptFilesExtensions) + transformSpec.configureCommonParameters() } } -private fun DependencyHandler.registerOnceDiscoverScriptExtensionsTransform() { +private fun DependencyHandler.registerOnceDiscoverScriptExtensionsTransform( + classLoadersCachingService: Provider, + compilerClasspath: NamedDomainObjectProvider +) { if (!extensions.extraProperties.has("DiscoverScriptExtensionsTransform")) { - registerDiscoverScriptExtensionsTransform() + registerDiscoverScriptExtensionsTransform(classLoadersCachingService, compilerClasspath) extensions.extraProperties["DiscoverScriptExtensionsTransform"] = true } } @@ -166,22 +183,15 @@ private val artifactType = Attribute.of("artifactType", String::class.java) private const val scriptFilesExtensions = "script-files-extensions" -private fun Configuration.discoverScriptExtensionsFiles() = - incoming.artifactView { - attributes { - it.attribute(artifactType, scriptFilesExtensions) - } - }.artifacts.artifactFiles - class ScriptingKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin { companion object { const val SCRIPTING_ARTIFACT_NAME = "kotlin-scripting-compiler-embeddable" - val SCRIPT_DEFINITIONS_OPTION = "script-definitions" - val SCRIPT_DEFINITIONS_CLASSPATH_OPTION = "script-definitions-classpath" - val DISABLE_SCRIPT_DEFINITIONS_FROM_CLSSPATH_OPTION = "disable-script-definitions-from-classpath" - val LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION = "script-resolver-environment" + const val SCRIPT_DEFINITIONS_OPTION = "script-definitions" + const val SCRIPT_DEFINITIONS_CLASSPATH_OPTION = "script-definitions-classpath" + const val DISABLE_SCRIPT_DEFINITIONS_FROM_CLASSPATH_OPTION = "disable-script-definitions-from-classpath" + const val LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION = "script-resolver-environment" } override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = kotlinCompilation !is AbstractKotlinNativeCompilation @@ -204,7 +214,7 @@ class ScriptingKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin { options += SubpluginOption(SCRIPT_DEFINITIONS_CLASSPATH_OPTION, path) } if (scriptingExtension.myDisableScriptDefinitionsFromClasspath) { - options += SubpluginOption(DISABLE_SCRIPT_DEFINITIONS_FROM_CLSSPATH_OPTION, "true") + options += SubpluginOption(DISABLE_SCRIPT_DEFINITIONS_FROM_CLASSPATH_OPTION, "true") } for (pair in scriptingExtension.myScriptResolverEnvironment) { options += SubpluginOption(LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION, "${pair.key}=${pair.value}") diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-build-tools-impl/kotlin-build-tools-impl.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-build-tools-impl/kotlin-build-tools-impl.pom index f9725289a9d..d1bba34fe4e 100644 --- a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-build-tools-impl/kotlin-build-tools-impl.pom +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-build-tools-impl/kotlin-build-tools-impl.pom @@ -50,5 +50,17 @@ ArtifactsTest.version runtime + + org.jetbrains.kotlin + kotlin-scripting-compiler-embeddable + ArtifactsTest.version + runtime + + + org.jetbrains.kotlin + kotlin-scripting-compiler-impl-embeddable + ArtifactsTest.version + runtime + diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-gradle-plugin/kotlin-gradle-plugin.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-gradle-plugin/kotlin-gradle-plugin.pom index 91ba4620b87..bfec31de9b8 100644 --- a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-gradle-plugin/kotlin-gradle-plugin.pom +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlin-gradle-plugin/kotlin-gradle-plugin.pom @@ -306,70 +306,6 @@ - - org.jetbrains.kotlin - kotlin-scripting-compiler-embeddable - ArtifactsTest.version - runtime - - - kotlin-reflect - org.jetbrains.kotlin - - - kotlin-stdlib-jdk8 - org.jetbrains.kotlin - - - kotlin-stdlib-jdk7 - org.jetbrains.kotlin - - - kotlin-stdlib - org.jetbrains.kotlin - - - kotlin-script-runtime - org.jetbrains.kotlin - - - kotlin-stdlib-common - org.jetbrains.kotlin - - - - - org.jetbrains.kotlin - kotlin-scripting-compiler-impl-embeddable - ArtifactsTest.version - runtime - - - kotlin-reflect - org.jetbrains.kotlin - - - kotlin-stdlib-jdk8 - org.jetbrains.kotlin - - - kotlin-stdlib-jdk7 - org.jetbrains.kotlin - - - kotlin-stdlib - org.jetbrains.kotlin - - - kotlin-script-runtime - org.jetbrains.kotlin - - - kotlin-stdlib-common - org.jetbrains.kotlin - - - org.jetbrains.kotlin kotlin-util-klib