From 0ac969a61785a9fa19e2aa80ce5ac1111d57a783 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Fri, 10 Aug 2018 19:26:02 +0300 Subject: [PATCH] Attempt to make loading of compiler plugins from kotlin-platform-native Gradle plugin Moved SubpluginEnviroment to separate file and made public some methods KotlinNativeCompile task now extends AbstractCompile so it could be passed to SubpluginEnviroment.loadSubplugins KotlinNativeBasePlugin now declares kotlinCompilerPluginClasspath configuration --- .../kotlin/gradle/plugin/KotlinPlugin.kt | 79 +-------------- .../gradle/plugin/KotlinPluginWrapper.kt | 2 +- .../gradle/plugin/SubpluginEnvironment.kt | 95 +++++++++++++++++++ .../gradle/tasks/CompilerPluginOptions.kt | 2 +- 4 files changed, 102 insertions(+), 76 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/SubpluginEnvironment.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index bcf00f8253b..4602395a8d3 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -22,7 +22,6 @@ import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.gradle.jvm.tasks.Jar import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry -import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension @@ -42,7 +41,7 @@ import java.util.* import java.util.concurrent.Callable import java.util.jar.Manifest -internal const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath" +const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath" internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath" val KOTLIN_DSL_NAME = "kotlin" val KOTLIN_JS_DSL_NAME = "kotlin2js" @@ -172,7 +171,7 @@ internal class Kotlin2JvmSourceSetProcessor( project.afterEvaluate { project -> val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile } - val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion) + val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val appliedPlugins = subpluginEnvironment.addSubpluginOptions( project, kotlinTask, javaTask, null, null, kotlinCompilation ) @@ -270,7 +269,7 @@ internal class Kotlin2JsSourceSetProcessor( kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath val outputDir = kotlinTask.outputFile.parentFile - val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion) + val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val appliedPlugins = subpluginEnvironment.addSubpluginOptions( project, kotlinTask, null, null, null, kotlinCompilation) @@ -321,7 +320,7 @@ internal class KotlinCommonSourceSetProcessor( } project.afterEvaluate { project -> - val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion) + val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val appliedPlugins = subpluginEnvironment.addSubpluginOptions( project, kotlinTask, null, null, null, kotlinCompilation ) @@ -678,7 +677,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT ) } - val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion) + val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion) forEachVariant(project) { variant -> val compilation = kotlinAndroidTarget.compilations.getByName(getVariantName(variant)) @@ -827,74 +826,6 @@ private fun SourceSet.clearJavaSrcDirs() { java.setSrcDirs(emptyList()) } -private fun loadSubplugins(project: Project, kotlinPluginVersion: String): SubpluginEnvironment = - try { - val klass = KotlinGradleSubplugin::class.java - val buildscriptClassloader = project.buildscript.classLoader - val klassFromBuildscript = try { - buildscriptClassloader.loadClass(klass.canonicalName) - } catch (e: ClassNotFoundException) { - null - } - - val classloader = if (klass == klassFromBuildscript) { - buildscriptClassloader - } else { - klass.classLoader - } - - val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, classloader) - .map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin) } - - SubpluginEnvironment(subplugins, kotlinPluginVersion) - } catch (e: NoClassDefFoundError) { - // Skip plugin loading if KotlinGradleSubplugin is not defined. - // It is true now for tests in kotlin-gradle-plugin-core. - project.logger.error("Could not load subplugins", e) - SubpluginEnvironment(listOf(), kotlinPluginVersion) - } - -internal class SubpluginEnvironment( - private val subplugins: List>, - private val kotlinPluginVersion: String -) { - fun addSubpluginOptions( - project: Project, - kotlinTask: AbstractKotlinCompile, - javaTask: AbstractCompile?, - variantData: Any?, - androidProjectHandler: AbstractAndroidProjectHandler?, - kotlinCompilation: KotlinCompilation? - ): List>> { - val pluginOptions = kotlinTask.pluginOptions - - val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) } - for (subplugin in appliedSubplugins) { - if (!subplugin.isApplicable(project, kotlinTask)) continue - - val pluginId = subplugin.getCompilerPluginId() - project.logger.kotlinDebug { "Loading subplugin $pluginId" } - - val artifact = subplugin.getPluginArtifact() - val artifactVersion = artifact.version ?: kotlinPluginVersion - val mavenCoordinate = "${artifact.groupId}:${artifact.artifactId}:$artifactVersion" - project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$PLUGIN_CLASSPATH_CONFIGURATION_NAME' configuration" } - project.dependencies.add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, mavenCoordinate) - - val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation) - val subpluginId = subplugin.getCompilerPluginId() - kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions) - - for (option in subpluginOptions) { - pluginOptions.addPluginArgument(subpluginId, option) - } - project.logger.kotlinDebug("Subplugin $pluginId loaded") - } - - return appliedSubplugins - } -} - internal fun Task.registerSubpluginOptionsAsInputs(subpluginId: String, subpluginOptions: List) { // There might be several options with the same key. We group them together // and add an index to the Gradle input property name to resolve possible duplication: diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index a6a3fa86bad..b444a23f019 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -148,7 +148,7 @@ open class KotlinMultiplatformPluginWrapper @Inject constructor( fun Project.getKotlinPluginVersion(): String? = plugins.asSequence().mapNotNull { (it as? KotlinBasePluginWrapper)?.kotlinPluginVersion }.firstOrNull() -private fun Any.loadKotlinVersionFromResource(log: Logger): String { +fun Plugin<*>.loadKotlinVersionFromResource(log: Logger): String { log.kotlinDebug("Loading version information") val props = Properties() val propFileName = "project.properties" diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/SubpluginEnvironment.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/SubpluginEnvironment.kt new file mode 100644 index 00000000000..92205367aa5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/SubpluginEnvironment.kt @@ -0,0 +1,95 @@ +package org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.Project +import org.gradle.api.tasks.compile.AbstractCompile +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile +import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions +import java.util.* + +class SubpluginEnvironment( + private val subplugins: List>, + private val kotlinPluginVersion: String +) { + companion object { + fun loadSubplugins(project: Project, kotlinPluginVersion: String): SubpluginEnvironment = + try { + val klass = KotlinGradleSubplugin::class.java + val buildscriptClassloader = project.buildscript.classLoader + val klassFromBuildscript = try { + buildscriptClassloader.loadClass(klass.canonicalName) + } catch (e: ClassNotFoundException) { + null + } + + val classloader = if (klass == klassFromBuildscript) { + buildscriptClassloader + } else { + klass.classLoader + } + + val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, classloader) + .map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin) } + + SubpluginEnvironment(subplugins, kotlinPluginVersion) + } catch (e: NoClassDefFoundError) { + // Skip plugin loading if KotlinGradleSubplugin is not defined. + // It is true now for tests in kotlin-gradle-plugin-core. + project.logger.error("Could not load subplugins", e) + SubpluginEnvironment(listOf(), kotlinPluginVersion) + } + } + + fun addSubpluginOptions( + project: Project, + kotlinTask: AbstractKotlinCompile, + javaTask: AbstractCompile? = null, + variantData: Any? = null, + androidProjectHandler: AbstractAndroidProjectHandler? = null, + kotlinCompilation: KotlinCompilation? = null + ): List>> = addSubpluginOptions( + project, + kotlinTask, + kotlinTask.pluginOptions, + javaTask, + variantData, + androidProjectHandler, + kotlinCompilation + ) + + fun addSubpluginOptions( + project: Project, + kotlinTask: AbstractCompile, + pluginOptions: CompilerPluginOptions, + javaTask: AbstractCompile? = null, + variantData: Any? = null, + androidProjectHandler: AbstractAndroidProjectHandler? = null, + kotlinCompilation: KotlinCompilation? = null + ): List>> { + val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) } + for (subplugin in appliedSubplugins) { + if (!subplugin.isApplicable(project, kotlinTask)) continue + + val pluginId = subplugin.getCompilerPluginId() + project.logger.kotlinDebug { "Loading subplugin $pluginId" } + + val artifact = subplugin.getPluginArtifact() + val artifactVersion = artifact.version ?: kotlinPluginVersion + val mavenCoordinate = "${artifact.groupId}:${artifact.artifactId}:$artifactVersion" + project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$PLUGIN_CLASSPATH_CONFIGURATION_NAME' configuration" } + project.dependencies.add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, mavenCoordinate) + + val subpluginOptions = + subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation) + val subpluginId = subplugin.getCompilerPluginId() + kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions) + + for (option in subpluginOptions) { + pluginOptions.addPluginArgument(subpluginId, option) + } + project.logger.kotlinDebug("Subplugin $pluginId loaded") + } + + return appliedSubplugins + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/CompilerPluginOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/CompilerPluginOptions.kt index 00ff85897a9..88ca0acb066 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/CompilerPluginOptions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/CompilerPluginOptions.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.gradle.tasks import org.jetbrains.kotlin.gradle.plugin.SubpluginOption import java.io.File -internal class CompilerPluginOptions { +class CompilerPluginOptions { private val mutableArguments = arrayListOf() internal val subpluginOptionsByPluginId =