org.jetbrains.kotlin.gradle.plugin.mpp.pm20.compilerPluginProvider.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
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.tasks.CompilerPluginOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData
import org.jetbrains.kotlin.gradle.utils.addGradlePluginMetadataAttributes
import org.jetbrains.kotlin.gradle.utils.newProperty
import org.jetbrains.kotlin.project.model.*
import java.io.File
internal fun Project.compilerPluginProviderForMetadata(
fragment: GradleKpmFragment,
compilationData: GradleKpmCommonFragmentMetadataCompilationData
) = compilerPluginDataProvider(compilationData, fragment::metadataCompilationPluginData)
internal fun Project.compilerPluginProviderForNativeMetadata(
fragment: GradleKpmFragment,
compilationData: GradleKpmNativeFragmentMetadataCompilationData
) = compilerPluginDataProvider(compilationData, fragment::nativeMetadataCompilationPluginData)
internal fun Project.compilerPluginProviderForPlatformCompilation(
variant: GradleKpmVariant,
compilationData: GradleKpmCompilationData<*>
) = compilerPluginDataProvider(compilationData, variant::platformCompilationPluginData)
internal fun GradleKpmCompilationData<*>.pluginClasspathConfigurationName() = "${compileKotlinTaskName}PluginClasspath"
private fun Project.compilerPluginDataProvider(
compilationData: GradleKpmCompilationData<*>,
pluginDataList: () -> List
): Provider {
return newProperty {
val configurationName = compilationData.pluginClasspathConfigurationName()
val builder = CompilerPluginOptionsBuilder(project, configurationName)
builder += pluginDataList()
builder.build()
}.apply { disallowUnsafeRead() }
}
private 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()
private val gradleOutputFiles = mutableSetOf()
operator fun plusAssign(pluginData: PluginData) {
artifacts += pluginData.artifact.toGradleCoordinates()
for (option in pluginData.options) {
pluginOptions.addPluginArgument(pluginData.pluginId, option.toSubpluginOption())
if (!option.isTransient) {
addToInputsOutputs(pluginData.pluginId, option)
}
}
}
operator fun plusAssign(pluginDataCollection: Collection) {
for (pluginData in pluginDataCollection) {
this += pluginData
}
}
private fun addToInputsOutputs(pluginId: String, option: PluginOption) {
when (option) {
is FilesOption ->
if (option.isOutput) {
gradleOutputFiles += option.files
} else {
gradleInputFiles += option.files
}
is StringOption -> gradleInputs
.getOrPut("${pluginId}.${option.key}") { mutableListOf() }
.add(option.value)
}
}
fun build(): KotlinCompilerPluginData {
val pluginClasspathConfiguration =
project.configurations.maybeCreate(configurationName).apply {
isCanBeConsumed = false
isCanBeResolved = true
isVisible = false
addGradlePluginMetadataAttributes(project)
}
artifacts.forEach { project.dependencies.add(configurationName, it) }
return KotlinCompilerPluginData(
classpath = pluginClasspathConfiguration,
options = pluginOptions,
inputsOutputsState = KotlinCompilerPluginData.InputsOutputsState(
inputs = gradleInputs.flattenWithIndex(),
inputFiles = gradleInputFiles,
outputFiles = gradleOutputFiles
)
)
}
private fun Map>.flattenWithIndex(): Map {
val result = mutableMapOf()
for ((key, values) in this) {
for ((index, value) in values.withIndex()) {
result["${key}.$index"] = value
}
}
return result
}
private fun PluginOption.toSubpluginOption() = when (this) {
is FilesOption -> FilesSubpluginOption(key, files)
is StringOption -> SubpluginOption(key, value)
}
private fun PluginData.ArtifactCoordinates.toGradleCoordinates(): String =
listOfNotNull(group, artifact, version).joinToString(":")
}