diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/mpp/KpmCompilerPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/mpp/KpmCompilerPlugin.kt index 35c0f0fed60..a00bcc02860 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/mpp/KpmCompilerPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/mpp/KpmCompilerPlugin.kt @@ -118,7 +118,7 @@ class KpmCompilerPluginTest { group = "test", artifact = artifact ), - options = options.map { PluginData.PluginOption(it.key, it.value) } + options = options.map { StringOption(it.key, it.value) } ) override fun forMetadataCompilation(fragment: KotlinModuleFragment) = metadataArtifact?.let(::pluginData) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt index 7b59c8c39f6..0e5b1339e1f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt @@ -7,12 +7,14 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.Project import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.plugin.FilesSubpluginOption import org.jetbrains.kotlin.gradle.plugin.SubpluginOption import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData import org.jetbrains.kotlin.gradle.utils.newProperty import org.jetbrains.kotlin.project.model.* +import java.io.File internal fun Project.compilerPluginProviderForMetadata( fragment: KotlinGradleFragment, @@ -35,29 +37,69 @@ private fun Project.compilerPluginDataProvider( compilationData: KotlinCompilationData<*>, pluginDataList: () -> List ): Provider { - val configurationName = compilationData.pluginClasspathConfigurationName() - val pluginClasspathConfiguration = - configurations.maybeCreate(configurationName).apply { - isCanBeConsumed = false - isCanBeResolved = true - isVisible = false - } - - val pluginOptions = CompilerPluginOptions() return newProperty { - for (pluginData in pluginDataList()) { - dependencies.add(pluginClasspathConfiguration.name, pluginData.artifact.toGradleCoordinates(project)) - pluginData.options.forEach { (key, value) -> - pluginOptions.addPluginArgument(pluginData.pluginId, SubpluginOption(key, value)) - } - } - - KotlinCompilerPluginData( - classpath = pluginClasspathConfiguration, - options = pluginOptions - ) + val configurationName = compilationData.pluginClasspathConfigurationName() + val builder = CompilerPluginOptionsBuilder(project, configurationName) + builder += pluginDataList() + builder.build() }.apply { finalizeValueOnRead() } } -private fun PluginData.ArtifactCoordinates.toGradleCoordinates(project: Project): String = - "$group:$artifact:${version ?: project.getKotlinPluginVersion()}" +internal class CompilerPluginOptionsBuilder( + private val project: Project, + private val configurationName: String +) { + private val pluginOptions = CompilerPluginOptions() + private val artifacts = mutableListOf() + private val gradleInputs = mutableMapOf() + private val gradleInputFiles = mutableSetOf() + + operator fun plusAssign(pluginData: PluginData) { + artifacts += pluginData.artifact.toGradleCoordinates() + + for (option in pluginData.options) { + pluginOptions.addPluginArgument(pluginData.pluginId, option.toSubpluginOption()) + + if (option.sensitive) { + addToInputs(pluginData.pluginId, option) + } + } + } + + operator fun plusAssign(pluginDataCollection: Collection) { + for (pluginData in pluginDataCollection) { + this += pluginData + } + } + + private fun addToInputs(pluginId: String, option: PluginOption) = when(option) { + is FilesOption -> gradleInputFiles += option.files + is StringOption -> gradleInputs["${pluginId}.${option.key}"] = option.value + } + + fun build(): KotlinCompilerPluginData { + val pluginClasspathConfiguration = + project.configurations.maybeCreate(configurationName).apply { + isCanBeConsumed = false + isCanBeResolved = true + isVisible = false + } + artifacts.forEach { project.dependencies.add(configurationName, it) } + + return KotlinCompilerPluginData( + classpath = pluginClasspathConfiguration, + options = pluginOptions, + inputs = gradleInputs, + inputFiles = gradleInputFiles + ) + } + + + private fun PluginOption.toSubpluginOption() = when (this) { + is FilesOption -> FilesSubpluginOption(key, files) + is StringOption -> SubpluginOption(key, value) + } + + private fun PluginData.ArtifactCoordinates.toGradleCoordinates(): String = + "$group:$artifact:${version ?: project.getKotlinPluginVersion()}" +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 2cefe9ff49a..23571c300f3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -783,5 +783,19 @@ data class KotlinCompilerPluginData( val classpath: FileCollection, @get:Internal - val options: CompilerPluginOptions + val options: CompilerPluginOptions, + + /** + * Used only for Up-to-date checks + */ + @get:Input + val inputs: Map, + + /** + * Used only for Up-to-date checks + */ + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + val inputFiles: Set ) + diff --git a/libraries/tools/kotlin-project-model/src/main/kotlin/KpmCompilerPlugin.kt b/libraries/tools/kotlin-project-model/src/main/kotlin/KpmCompilerPlugin.kt index f0dd7816025..0b913a83170 100644 --- a/libraries/tools/kotlin-project-model/src/main/kotlin/KpmCompilerPlugin.kt +++ b/libraries/tools/kotlin-project-model/src/main/kotlin/KpmCompilerPlugin.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.project.model +import java.io.File + /** * Adapts Kotlin Compiler Plugin for Multiplatform Kotlin Project Model * Build System uses this interface to identify applicable plugin artifacts and its options @@ -45,13 +47,30 @@ data class PluginData( val artifact: String, val version: String? = null ) - - data class PluginOption( - val key: String, - val value: String - ) } +sealed class PluginOption { + abstract val key: String + + /** + * when true a value of given plugin option is sensitive for incremental compilation + * when false compilation task can be skipped even if value differs from previous one + */ + abstract val sensitive: Boolean +} + +data class StringOption( + override val key: String, + val value: String, + override val sensitive: Boolean = true +) : PluginOption() + +data class FilesOption( + override val key: String, + val files: List, + override val sensitive: Boolean = true +) : PluginOption() + // TODO: It should be part of "Compilation Process": KotlinModule.compilationRequestFor(METADATA | PLATFORM) -> CompilationRequest // But there is no such thing at the moment :) fun KotlinModuleFragment.metadataCompilationPluginData(): List = @@ -81,8 +100,7 @@ abstract class BasicKpmCompilerPlugin : KpmCompilerPlugin { protected abstract fun nativePluginArtifact(): PluginData.ArtifactCoordinates? - protected abstract val pluginOptions: List - + protected abstract val pluginOptions: List override fun forMetadataCompilation(fragment: KotlinModuleFragment) = pluginDataOrNull(commonPluginArtifact())