Introduce new API for Kotlin compiler support Gradle plugins
The old API was too specific for the Kotlin internal use cases and leaked some abstractions due to the missing target-compilation project model. One of such leaking abstractions was the Gradle tasks being exposed to the subplugin, which required the tasks to instantiate in order for the subplugin to apply. This violated task configuration avoidance, so the old API could never work in compliance with TCA. Introduce the new KotlinCompilerPluginSupportPlugin API that uses the compilations instead of the tasks and is TCA-compliant.
This commit is contained in:
+42
-2
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||
import java.io.File
|
||||
@@ -62,6 +65,12 @@ enum class FilesOptionKind {
|
||||
/** Defines a subplugin option that should be excluded from Gradle input/output checks */
|
||||
open class InternalSubpluginOption(key: String, value: String) : SubpluginOption(key, value)
|
||||
|
||||
// Deprecated because most calls require the tasks to be instantiated, which is not compatible with Gradle task configuration avoidance.
|
||||
@Deprecated(
|
||||
message = "This interface will be removed due to performance considerations. " +
|
||||
"Please use the KotlinCompilerPluginSupportPlugin interface instead.",
|
||||
replaceWith = ReplaceWith("KotlinCompilerPluginSupportPlugin")
|
||||
)
|
||||
interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
|
||||
fun isApplicable(project: Project, task: AbstractCompile): Boolean
|
||||
|
||||
@@ -75,8 +84,8 @@ interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
|
||||
): List<SubpluginOption>
|
||||
|
||||
fun getSubpluginKotlinTasks(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile
|
||||
): List<AbstractCompile> = emptyList()
|
||||
|
||||
fun getCompilerPluginId(): String
|
||||
@@ -85,6 +94,37 @@ interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
|
||||
fun getNativeCompilerPluginArtifact(): SubpluginArtifact? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Gradle plugin implementing support for a Kotlin compiler plugin.
|
||||
*
|
||||
* In order to be discovered, it should be applied to the project as an ordinary Gradle [Plugin] before the
|
||||
* Kotlin plugin inspects the project model in an afterEvaluate handler.
|
||||
*
|
||||
* The default implementation of [apply]
|
||||
* doesn't do anything, but it can be overridden.
|
||||
*
|
||||
* Then its [isApplicable] is checked against compilations of the project, and if it returns true,
|
||||
* then [applyToCompilation] may be called later.
|
||||
*/
|
||||
interface KotlinCompilerPluginSupportPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) = Unit
|
||||
|
||||
fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean
|
||||
|
||||
/**
|
||||
* Configures the compiler plugin to be incorporated into a specific [kotlinCompilation].
|
||||
* This function is only called on [kotlinCompilation]s approved by [isApplicable].
|
||||
* The [Provider] returned from this function may never get queried if the compilation is avoided in the current build.
|
||||
*/
|
||||
fun applyToCompilation(
|
||||
kotlinCompilation: KotlinCompilation<*>
|
||||
): Provider<List<SubpluginOption>>
|
||||
|
||||
fun getCompilerPluginId(): String
|
||||
fun getPluginArtifact(): SubpluginArtifact
|
||||
fun getNativeCompilerPluginArtifact(): SubpluginArtifact? = null
|
||||
}
|
||||
|
||||
open class SubpluginArtifact(val groupId: String, val artifactId: String, val version: String? = null)
|
||||
|
||||
class JetBrainsSubpluginArtifact(artifactId: String) : SubpluginArtifact(groupId = "org.jetbrains.kotlin", artifactId = artifactId)
|
||||
|
||||
+43
-85
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin
|
||||
import com.android.build.gradle.*
|
||||
import com.android.build.gradle.api.AndroidSourceSet
|
||||
import com.android.build.gradle.api.BaseVariant
|
||||
import com.android.build.gradle.api.SourceKind
|
||||
import com.android.builder.model.SourceProvider
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.ExternalDependency
|
||||
@@ -29,7 +30,6 @@ import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.Upload
|
||||
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.gradle.dsl.*
|
||||
@@ -207,20 +207,9 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
|
||||
ScriptingGradleSubplugin.configureForSourceSet(project, kotlinCompilation.compilationName)
|
||||
|
||||
// TODO: here, the tasks are always triggered for configuration; once the subplugins are able to work without task instances,
|
||||
// ensure that task configuration is properly avoided here;
|
||||
project.whenEvaluated {
|
||||
val kotlinTaskInstance = kotlinTask.get()
|
||||
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
|
||||
|
||||
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTaskInstance, javaTask, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { plugin -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> plugin.source(sourceSet.kotlin) } }
|
||||
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
||||
|
||||
javaSourceSet?.let { java ->
|
||||
val javaTask = project.tasks.withType<AbstractCompile>().named(java.compileJavaTaskName)
|
||||
@@ -274,29 +263,22 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
}
|
||||
|
||||
// outputFile can be set later during the configuration phase, get it only after the phase:
|
||||
project.runOnceAfterEvaluated("Kotlin2JsSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.get()
|
||||
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath
|
||||
val outputDir = kotlinTaskInstance.outputFile.parentFile
|
||||
project.whenEvaluated {
|
||||
kotlinTask.configure { kotlinTaskInstance ->
|
||||
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath
|
||||
val outputDir = kotlinTaskInstance.outputFile.parentFile
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " +
|
||||
"matches the project root directory '${project.rootDir}'.\n" +
|
||||
"Gradle will not be able to build the project because of the root directory lock.\n" +
|
||||
"To fix this, consider using the default outputFile location instead of providing it explicitly."
|
||||
)
|
||||
kotlinTaskInstance.destinationDir = outputDir
|
||||
}
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTaskInstance, null, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " +
|
||||
"matches the project root directory '${project.rootDir}'.\n" +
|
||||
"Gradle will not be able to build the project because of the root directory lock.\n" +
|
||||
"To fix this, consider using the default outputFile location instead of providing it explicitly."
|
||||
)
|
||||
|
||||
kotlinTaskInstance.destinationDir = outputDir
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { task -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } }
|
||||
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,17 +334,17 @@ internal class KotlinJsIrSourceSetProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
project.whenEvaluated {
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
||||
}
|
||||
|
||||
// outputFile can be set later during the configuration phase, get it only after the phase:
|
||||
project.runOnceAfterEvaluated("KotlinJsIrSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.get()
|
||||
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath
|
||||
val outputDir = kotlinTaskInstance.outputFile.parentFile
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTaskInstance, null, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " +
|
||||
@@ -372,10 +354,6 @@ internal class KotlinJsIrSourceSetProcessor(
|
||||
)
|
||||
|
||||
kotlinTaskInstance.destinationDir = outputDir
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { task -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,15 +372,9 @@ internal class KotlinCommonSourceSetProcessor(
|
||||
project.locateTask<Task>(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
|
||||
}
|
||||
|
||||
project.runOnceAfterEvaluated("KotlinCommonSourceSetProcessor.doTargetSpecificProcessing", kotlinTask) {
|
||||
val kotlinTaskInstance = kotlinTask.get()
|
||||
project.whenEvaluated {
|
||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTaskInstance, null, null, null, kotlinCompilation
|
||||
)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) }
|
||||
.forEach { kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> it.source(sourceSet.kotlin) } }
|
||||
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,7 +751,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
abstract fun getLibraryOutputTask(variant: BaseVariant): Any?
|
||||
|
||||
protected abstract fun getSourceProviders(variantData: BaseVariant): Iterable<SourceProvider>
|
||||
protected abstract fun getAllJavaSources(variantData: BaseVariant): Iterable<File>
|
||||
protected abstract fun getJavaTask(variantData: BaseVariant): AbstractCompile?
|
||||
protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariant, javaSourceDirectory: File): Unit
|
||||
|
||||
@@ -871,7 +842,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
postprocessVariant(variant, compilation, project, ext, plugin)
|
||||
|
||||
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
|
||||
applySubplugins(project, compilation, variant, subpluginEnvironment)
|
||||
subpluginEnvironment.addSubpluginOptions(project, compilation)
|
||||
}
|
||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||
|
||||
@@ -1027,45 +998,32 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
compilation.associateWith(testedCompilation)
|
||||
}
|
||||
|
||||
val kotlinTask = compilation.compileKotlinTask
|
||||
configureSources(kotlinTask, variantData, compilation)
|
||||
val kotlinTask = compilation.compileKotlinTaskProvider
|
||||
processAndroidKotlinAndJavaSources(
|
||||
compilation,
|
||||
addKotlinSources = { kotlinSourceSet -> compilation.source(kotlinSourceSet) },
|
||||
addJavaSources = { sources -> compilation.compileKotlinTaskProvider.configure { it.source(sources) } }
|
||||
)
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applySubplugins(
|
||||
project: Project,
|
||||
compilation: KotlinCompilation<*>,
|
||||
variantData: BaseVariant,
|
||||
subpluginEnvironment: SubpluginEnvironment
|
||||
) {
|
||||
val kotlinTask = project.tasks.getByName(compilation.compileKotlinTaskName) as KotlinCompile
|
||||
val javaTask = getJavaTask(variantData)
|
||||
private fun getAllJavaSources(variantData: BaseVariant): Iterable<File> =
|
||||
variantData.getSourceFolders(SourceKind.JAVA).map { it.dir }
|
||||
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), this, null
|
||||
)
|
||||
internal fun processAndroidKotlinAndJavaSources(
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
addKotlinSources: (KotlinSourceSet) -> Unit,
|
||||
addJavaSources: (Iterable<File>) -> Unit
|
||||
) {
|
||||
val variantData = compilation.androidVariant
|
||||
|
||||
appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { configureSources(it, variantData, null) }
|
||||
for (provider in variantData.sourceSets) {
|
||||
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
|
||||
addKotlinSources(kotlinSourceSet)
|
||||
}
|
||||
|
||||
private fun configureSources(compileTask: AbstractCompile, variantData: BaseVariant, compilation: KotlinCompilation<*>?) {
|
||||
val logger = compileTask.project.logger
|
||||
|
||||
for (provider in getSourceProviders(variantData)) {
|
||||
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
|
||||
if (compilation != null) {
|
||||
compilation.source(kotlinSourceSet)
|
||||
} else {
|
||||
compileTask.source(kotlinSourceSet.kotlin)
|
||||
}
|
||||
}
|
||||
|
||||
for (javaSrcDir in getAllJavaSources(variantData)) {
|
||||
compileTask.source(javaSrcDir)
|
||||
logger.kotlinDebug("Source directory $javaSrcDir was added to kotlin source for ${compileTask.name}")
|
||||
}
|
||||
}
|
||||
addJavaSources(getAllJavaSources(variantData))
|
||||
}
|
||||
|
||||
internal fun configureJavaTask(
|
||||
|
||||
+109
-37
@@ -1,20 +1,30 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.thisTaskProvider
|
||||
import java.util.*
|
||||
|
||||
class SubpluginEnvironment(
|
||||
private val subplugins: List<KotlinGradleSubplugin<AbstractCompile>>,
|
||||
private val subplugins: List<KotlinCompilerPluginSupportPlugin>,
|
||||
private val kotlinPluginVersion: String
|
||||
) {
|
||||
companion object {
|
||||
fun loadSubplugins(project: Project, kotlinPluginVersion: String): SubpluginEnvironment =
|
||||
try {
|
||||
@Suppress("DEPRECATION") // support for the deprecated plugin API
|
||||
val klass = KotlinGradleSubplugin::class.java
|
||||
val buildscriptClassloader = project.buildscript.classLoader
|
||||
val klassFromBuildscript = try {
|
||||
@@ -29,10 +39,14 @@ class SubpluginEnvironment(
|
||||
klass.classLoader
|
||||
}
|
||||
|
||||
val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, classloader)
|
||||
.map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin<AbstractCompile>) }
|
||||
val result = project.plugins.filterIsInstance<KotlinCompilerPluginSupportPlugin>()
|
||||
|
||||
SubpluginEnvironment(subplugins, kotlinPluginVersion)
|
||||
@Suppress("DEPRECATION", "UNCHECKED_CAST")
|
||||
val compatibilitySubplugins = ServiceLoader.load(klass, classloader).map {
|
||||
LegacyKotlinCompilerPluginSupportPlugin(it as KotlinGradleSubplugin<AbstractCompile>)
|
||||
}
|
||||
|
||||
SubpluginEnvironment(result + compatibilitySubplugins, kotlinPluginVersion)
|
||||
} catch (e: NoClassDefFoundError) {
|
||||
// Skip plugin loading if KotlinGradleSubplugin is not defined.
|
||||
// It is true now for tests in kotlin-gradle-plugin-core.
|
||||
@@ -41,35 +55,13 @@ class SubpluginEnvironment(
|
||||
}
|
||||
}
|
||||
|
||||
fun <C : CommonCompilerArguments> addSubpluginOptions(
|
||||
project: Project,
|
||||
kotlinTask: AbstractKotlinCompile<C>,
|
||||
javaTask: AbstractCompile? = null,
|
||||
variantData: Any? = null,
|
||||
androidProjectHandler: AbstractAndroidProjectHandler? = null,
|
||||
kotlinCompilation: KotlinCompilation<*>? = null
|
||||
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> = 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<KotlinGradleSubplugin<AbstractCompile>> {
|
||||
val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) }
|
||||
kotlinCompilation: KotlinCompilation<*>
|
||||
): List<KotlinCompilerPluginSupportPlugin> {
|
||||
val appliedSubplugins = subplugins.filter { it.isApplicable(kotlinCompilation) }
|
||||
for (subplugin in appliedSubplugins) {
|
||||
if (!subplugin.isApplicable(project, kotlinTask)) continue
|
||||
if (!subplugin.isApplicable(kotlinCompilation)) continue
|
||||
|
||||
val pluginId = subplugin.getCompilerPluginId()
|
||||
project.logger.kotlinDebug { "Loading subplugin $pluginId" }
|
||||
@@ -82,24 +74,104 @@ class SubpluginEnvironment(
|
||||
project.addMavenDependency(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME, artifact)
|
||||
}
|
||||
|
||||
val subpluginOptions =
|
||||
subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation)
|
||||
val subpluginOptionsProvider = subplugin.applyToCompilation(kotlinCompilation)
|
||||
val subpluginId = subplugin.getCompilerPluginId()
|
||||
kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
|
||||
|
||||
for (option in subpluginOptions) {
|
||||
pluginOptions.addPluginArgument(subpluginId, option)
|
||||
kotlinCompilation.compileKotlinTaskProvider.configure {
|
||||
val pluginOptions = it.getPluginOptions()
|
||||
val subpluginOptions = subpluginOptionsProvider.get()
|
||||
for (option in subpluginOptions) {
|
||||
pluginOptions.addPluginArgument(subpluginId, option)
|
||||
}
|
||||
it.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
|
||||
}
|
||||
|
||||
project.logger.kotlinDebug("Subplugin $pluginId loaded")
|
||||
|
||||
if (subplugin is LegacyKotlinCompilerPluginSupportPlugin) {
|
||||
subplugin.getPluginKotlinTasks(kotlinCompilation).forEach { task ->
|
||||
addCompilationSourcesToExternalCompileTask(kotlinCompilation, task.thisTaskProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appliedSubplugins
|
||||
}
|
||||
|
||||
private fun KotlinCompile<*>.getPluginOptions(): CompilerPluginOptions = when (this) {
|
||||
is AbstractKotlinCompile<*> -> pluginOptions
|
||||
is KotlinNativeCompile -> compilerPluginOptions
|
||||
else -> error("Unexpected task ${this.name}, class: ${this.javaClass}")
|
||||
}
|
||||
|
||||
private fun Project.addMavenDependency(configuration: String, artifact: SubpluginArtifact) {
|
||||
val artifactVersion = artifact.version ?: kotlinPluginVersion
|
||||
val mavenCoordinate = "${artifact.groupId}:${artifact.artifactId}:$artifactVersion"
|
||||
project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$configuration' configuration" }
|
||||
project.dependencies.add(configuration, mavenCoordinate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun addCompilationSourcesToExternalCompileTask(compilation: KotlinCompilation<*>, task: TaskProvider<out AbstractCompile>) {
|
||||
if (compilation is KotlinJvmAndroidCompilation) {
|
||||
processAndroidKotlinAndJavaSources(
|
||||
compilation,
|
||||
addKotlinSources = { sourceSet -> task.configure { it.source(sourceSet.kotlin) } },
|
||||
addJavaSources = { sources -> task.configure { it.source(sources) }}
|
||||
)
|
||||
} else {
|
||||
task.configure { taskInstance ->
|
||||
compilation.allKotlinSourceSets.forEach { sourceSet -> taskInstance.source(sourceSet.kotlin) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class LegacyKotlinCompilerPluginSupportPlugin(
|
||||
@Suppress("deprecation") // support for deprecated API
|
||||
val oldPlugin: KotlinGradleSubplugin<AbstractCompile>
|
||||
): KotlinCompilerPluginSupportPlugin {
|
||||
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean =
|
||||
oldPlugin.isApplicable(kotlinCompilation.target.project, kotlinCompilation.compileKotlinTaskProvider.get() as AbstractCompile)
|
||||
|
||||
override fun applyToCompilation(
|
||||
kotlinCompilation: KotlinCompilation<*>
|
||||
): Provider<List<SubpluginOption>> {
|
||||
val project = kotlinCompilation.target.project
|
||||
|
||||
val androidProjectHandlerOrNull: AbstractAndroidProjectHandler? = if (kotlinCompilation is KotlinJvmAndroidCompilation)
|
||||
KotlinAndroidPlugin.androidTargetHandler(
|
||||
checkNotNull(project.getKotlinPluginVersion()),
|
||||
kotlinCompilation.target as KotlinAndroidTarget
|
||||
) else null
|
||||
|
||||
val variantData = (kotlinCompilation as? KotlinJvmAndroidCompilation)?.androidVariant
|
||||
|
||||
val result = oldPlugin.apply(
|
||||
project,
|
||||
kotlinCompilation.compileKotlinTask as AbstractCompile,
|
||||
findJavaTaskForKotlinCompilation(kotlinCompilation)?.get(),
|
||||
variantData,
|
||||
androidProjectHandlerOrNull,
|
||||
if (variantData != null) null else kotlinCompilation
|
||||
)
|
||||
|
||||
return project.provider { result }
|
||||
}
|
||||
|
||||
fun getPluginKotlinTasks(compilation: KotlinCompilation<*>): List<AbstractCompile> {
|
||||
val project = compilation.target.project
|
||||
return oldPlugin.getSubpluginKotlinTasks(project, compilation.compileKotlinTask as AbstractCompile)
|
||||
}
|
||||
|
||||
override fun getCompilerPluginId(): String = oldPlugin.getCompilerPluginId()
|
||||
override fun getPluginArtifact(): SubpluginArtifact = oldPlugin.getPluginArtifact()
|
||||
override fun getNativeCompilerPluginArtifact(): SubpluginArtifact? = oldPlugin.getNativeCompilerPluginArtifact()
|
||||
}
|
||||
|
||||
internal fun findJavaTaskForKotlinCompilation(compilation: KotlinCompilation<*>): TaskProvider<out JavaCompile>? =
|
||||
when (compilation) {
|
||||
is KotlinJvmAndroidCompilation -> compilation.compileJavaTaskProvider
|
||||
is KotlinWithJavaCompilation -> compilation.compileJavaTaskProvider
|
||||
is KotlinJvmCompilation -> compilation.compileJavaTaskProvider // may be null for Kotlin-only JVM target in MPP
|
||||
else -> null
|
||||
}
|
||||
-3
@@ -89,9 +89,6 @@ class Android25ProjectHandler(
|
||||
override fun getSourceProviders(variantData: BaseVariant): Iterable<SourceProvider> =
|
||||
variantData.sourceSets
|
||||
|
||||
override fun getAllJavaSources(variantData: BaseVariant): Iterable<File> =
|
||||
variantData.getSourceFolders(SourceKind.JAVA).map { it.dir }
|
||||
|
||||
override fun getFlavorNames(variant: BaseVariant): List<String> = variant.productFlavors.map { it.name }
|
||||
|
||||
override fun getBuildTypeName(variant: BaseVariant): String = variant.buildType.name
|
||||
|
||||
Reference in New Issue
Block a user