Update existing plugin implementations to use KotlinCompilation
Add default implementations for KotlinTarget and KotlinCompilation (some of them are used in code added by further commits). Refactor AbstractKotlinPlugin so that parts of its logic can be easily applied outside the plugin (needed for MPP plugin later). The single platform Kotlin plugins having Kotlin compiled along with Java will now create a KotlinCompilation and a KotlinSourceSet per Java source set or per Android variant. The build configuration logic will use KotlinCompilation objects rather than Java or Android plugin entities. Subplugins API and implementations are updated to use KotlinCompilation.
This commit is contained in:
+7
-11
@@ -16,13 +16,9 @@
|
||||
|
||||
package example
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
|
||||
class ExampleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
|
||||
@@ -31,12 +27,12 @@ class ExampleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
println("ExampleSubplugin loaded")
|
||||
return listOf(SubpluginOption("exampleKey", "exampleValue"))
|
||||
|
||||
+7
-13
@@ -18,16 +18,10 @@ package org.jetbrains.kotlin.allopen.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.allopen.gradle.model.builder.AllOpenModelBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class AllOpenGradleSubplugin @Inject internal constructor(private val registry: ToolingModelBuilderRegistry) : Plugin<Project> {
|
||||
@@ -56,12 +50,12 @@ class AllOpenKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = AllOpenGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!AllOpenGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
+6
-7
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import java.io.File
|
||||
|
||||
@@ -52,12 +51,12 @@ interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
|
||||
fun isApplicable(project: Project, task: AbstractCompile): Boolean
|
||||
|
||||
fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption>
|
||||
|
||||
fun getSubpluginKotlinTasks(
|
||||
|
||||
+25
-7
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptTask
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||
import java.io.File
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -36,13 +38,15 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
|
||||
}
|
||||
}
|
||||
|
||||
override fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariant,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile) {
|
||||
|
||||
override fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariant,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
) {
|
||||
val preJavaKotlinOutputFiles = mutableListOf<File>().apply {
|
||||
add(kotlinTask.destinationDir)
|
||||
if (Kapt3GradleSubplugin.isEnabled(project)) {
|
||||
@@ -95,6 +99,20 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
|
||||
return variantData.mergeResources?.computeResourceSetList0() ?: emptyList()
|
||||
}
|
||||
|
||||
override fun setUpDependencyResolution(variant: BaseVariant, compilation: KotlinJvmAndroidCompilation) {
|
||||
val project = compilation.target.project
|
||||
|
||||
compilation.compileDependencyFiles = variant.compileConfiguration.apply {
|
||||
usesPlatformOf(compilation.target)
|
||||
project.addExtendsFromRelation(name, compilation.compileDependencyConfigurationName)
|
||||
}
|
||||
|
||||
compilation.runtimeDependencyFiles = variant.runtimeConfiguration.apply {
|
||||
usesPlatformOf(compilation.target)
|
||||
project.addExtendsFromRelation(name, compilation.runtimeDependencyConfigurationName)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class KaptVariant(variantData: BaseVariant) : KaptVariantData<BaseVariant>(variantData) {
|
||||
override val name: String = getVariantName(variantData)
|
||||
override val sourceProviders: Iterable<SourceProvider> = getSourceProviders(variantData)
|
||||
|
||||
+13
-3
@@ -16,13 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.plugins.DslObject
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>) {
|
||||
val kotlinExt = extensions.create("kotlin", extensionClass.java)
|
||||
private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
|
||||
|
||||
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>): KotlinProjectExtension {
|
||||
val kotlinExt = extensions.create(KOTLIN_PROJECT_EXTENSION_NAME, extensionClass.java)
|
||||
DslObject(kotlinExt).extensions.create("experimental", ExperimentalExtension::class.java)
|
||||
return kotlinExtension
|
||||
}
|
||||
|
||||
internal val Project.kotlinExtension: KotlinProjectExtension
|
||||
@@ -38,7 +44,11 @@ open class KotlinProjectExtension {
|
||||
internal set(value) { DslObject(this).extensions.add("sourceSets", value) }
|
||||
}
|
||||
|
||||
open class KotlinJvmProjectExtension : KotlinProjectExtension() {
|
||||
open class KotlinSingleJavaTargetExtension : KotlinProjectExtension() {
|
||||
internal lateinit var target: KotlinWithJavaTarget
|
||||
}
|
||||
|
||||
open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() {
|
||||
/**
|
||||
* With Gradle 4.0+, disables the separate output directory for Kotlin, falling back to sharing the deprecated
|
||||
* single classes directory per source set. With Gradle < 4.0, has no effect.
|
||||
|
||||
+6
-7
@@ -25,7 +25,6 @@ import com.android.build.gradle.internal.variant.TestVariantData
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.UnknownDomainObjectException
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.gradle.model.builder.KotlinAndroidExtensionModelBuilder
|
||||
@@ -90,12 +89,12 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
val androidExtension = project.extensions.getByName("android") as? BaseExtension ?: return emptyList()
|
||||
val androidExtensionsExtension = project.extensions.getByType(AndroidExtensionsExtension::class.java)
|
||||
|
||||
+25
-21
@@ -158,10 +158,10 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
private inner class Kapt3SubpluginContext(
|
||||
val project: Project,
|
||||
val kotlinCompile: KotlinCompile,
|
||||
val javaCompile: AbstractCompile,
|
||||
val javaCompile: AbstractCompile?,
|
||||
val kaptVariantData: KaptVariantData<*>?,
|
||||
val sourceSetName: String,
|
||||
val javaSourceSet: SourceSet?,
|
||||
val kotlinCompilation: KotlinCompilation?,
|
||||
val kaptExtension: KaptExtension,
|
||||
val kaptClasspathConfigurations: List<Configuration>
|
||||
) {
|
||||
@@ -171,14 +171,14 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
assert((variantData != null) xor (javaSourceSet != null))
|
||||
assert((variantData != null) xor (kotlinCompilation != null))
|
||||
|
||||
val buildDependencies = arrayListOf<TaskDependency>()
|
||||
val kaptConfigurations = arrayListOf<Configuration>()
|
||||
@@ -200,10 +200,10 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptVariantData.name
|
||||
}
|
||||
else {
|
||||
if (javaSourceSet == null) error("Java source set should not be null")
|
||||
if (kotlinCompilation == null) error("In non-Android projects, Kotlin compilation should not be null")
|
||||
|
||||
handleSourceSet(javaSourceSet.name)
|
||||
javaSourceSet.name
|
||||
handleSourceSet(kotlinCompilation.compilationName)
|
||||
kotlinCompilation.compilationName
|
||||
}
|
||||
|
||||
val kaptExtension = project.extensions.getByType(KaptExtension::class.java)
|
||||
@@ -212,7 +212,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
|
||||
val context = Kapt3SubpluginContext(
|
||||
project, kotlinCompile, javaCompile,
|
||||
kaptVariantData, sourceSetName, javaSourceSet, kaptExtension, nonEmptyKaptConfigurations
|
||||
kaptVariantData, sourceSetName, kotlinCompilation, kaptExtension, nonEmptyKaptConfigurations
|
||||
)
|
||||
|
||||
val kaptGenerateStubsTask = context.createKaptGenerateStubsTask()
|
||||
@@ -245,7 +245,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
pluginOptions += SubpluginOption("aptMode", aptMode)
|
||||
disableAnnotationProcessingInJavaTask()
|
||||
|
||||
javaCompile.source(generatedFilesDir)
|
||||
javaCompile?.source(generatedFilesDir)
|
||||
|
||||
pluginOptions += FilesSubpluginOption("sources", listOf(generatedFilesDir))
|
||||
pluginOptions += FilesSubpluginOption("classes", listOf(getKaptGeneratedClassesDir(project, sourceSetName)))
|
||||
@@ -362,18 +362,22 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptTask.kotlinSourcesDestinationDir = kotlinSourcesOutputDir
|
||||
kaptTask.classesDir = classesOutputDir
|
||||
|
||||
javaSourceSet?.output?.apply {
|
||||
if (tryAddClassesDir { project.files(classesOutputDir).builtBy(kaptTask) }) {
|
||||
kotlinCompile.attachClassesDir { classesOutputDir }
|
||||
kotlinCompilation?.run {
|
||||
output.apply {
|
||||
if (tryAddClassesDir { project.files(classesOutputDir).builtBy(kaptTask) }) {
|
||||
kotlinCompile.attachClassesDir { classesOutputDir }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlinCompile.source(sourcesOutputDir, kotlinSourcesOutputDir)
|
||||
|
||||
if (kaptVariantData != null) {
|
||||
kaptVariantData.registerGeneratedJavaSource(project, kaptTask, javaCompile)
|
||||
} else {
|
||||
registerGeneratedJavaSource(kaptTask, javaCompile)
|
||||
if (javaCompile != null) {
|
||||
if (kaptVariantData != null) {
|
||||
kaptVariantData.registerGeneratedJavaSource(project, kaptTask, javaCompile)
|
||||
} else {
|
||||
registerGeneratedJavaSource(kaptTask, javaCompile)
|
||||
}
|
||||
}
|
||||
|
||||
kaptTask.kaptClasspathConfigurations = kaptClasspathConfigurations
|
||||
|
||||
+41
-39
@@ -21,9 +21,8 @@ import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
|
||||
abstract class KotlinPlatformPluginBase(protected val platformName: String) : Plugin<Project> {
|
||||
@@ -110,7 +109,10 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
// Since the two projects may add source sets in arbitrary order, and both may do that after the plugin is applied,
|
||||
// we need to handle all source sets of the two projects and connect them once we get a match:
|
||||
// todo warn if no match found
|
||||
matchSymmetricallyByNames(commonProject.sourceSets, namedSourceSetsContainer(platformProject)) { commonSourceSet, _ ->
|
||||
matchSymmetricallyByNames(
|
||||
getKotlinSourceSetsSafe(commonProject),
|
||||
namedSourceSetsContainer(platformProject)
|
||||
) { commonSourceSet: Named, _ ->
|
||||
addCommonSourceSetToPlatformSourceSet(commonSourceSet, platformProject)
|
||||
}
|
||||
}
|
||||
@@ -121,13 +123,13 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
* regardless of the order in which they are added to the containers.
|
||||
*/
|
||||
private fun <A, B> matchSymmetricallyByNames(
|
||||
containerA: NamedDomainObjectContainer<A>,
|
||||
containerB: NamedDomainObjectContainer<B>,
|
||||
containerA: NamedDomainObjectCollection<out A>,
|
||||
containerB: NamedDomainObjectCollection<out B>,
|
||||
whenMatched: (A, B) -> Unit
|
||||
) {
|
||||
val matchedNames = mutableSetOf<String>()
|
||||
|
||||
fun <T, R> NamedDomainObjectContainer<T>.matchAllWith(other: NamedDomainObjectContainer<R>, match: (T, R) -> Unit) {
|
||||
fun <T, R> NamedDomainObjectCollection<T>.matchAllWith(other: NamedDomainObjectCollection<R>, match: (T, R) -> Unit) {
|
||||
this@matchAllWith.all { item ->
|
||||
val itemName = this@matchAllWith.namer.determineName(item)
|
||||
if (itemName !in matchedNames) {
|
||||
@@ -144,36 +146,38 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
}
|
||||
|
||||
protected open fun namedSourceSetsContainer(project: Project): NamedDomainObjectContainer<*> =
|
||||
project.sourceSets
|
||||
project.kotlinExtension.sourceSets
|
||||
|
||||
protected open fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: SourceSet, platformProject: Project) {
|
||||
val platformTask = platformProject.tasks
|
||||
.filterIsInstance<AbstractKotlinCompile<*>>()
|
||||
.firstOrNull { it.sourceSetName == commonSourceSet.name }
|
||||
protected open fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: Named, platformProject: Project) {
|
||||
platformProject.whenEvaluated { // At the point when the source set in the platform module is created, the task does not exist
|
||||
val platformTask = platformProject.tasks
|
||||
.filterIsInstance<AbstractKotlinCompile<*>>()
|
||||
.single { it.sourceSetName == commonSourceSet.name }
|
||||
|
||||
platformTask?.source(commonSourceSet.kotlin!!)
|
||||
platformTask.source(getKotlinSourceDirectorySetSafe(commonSourceSet))
|
||||
}
|
||||
}
|
||||
|
||||
protected val SourceSet.kotlin: SourceDirectorySet?
|
||||
get() {
|
||||
// Access through reflection, because another project's KotlinSourceSet might be loaded
|
||||
// by a different class loader:
|
||||
val convention = (getConvention("kotlin") ?: getConvention("kotlin2js")) ?: return null
|
||||
val kotlinSourceSetIface = convention.javaClass.interfaces.find { it.name == KotlinSourceSet::class.qualifiedName }
|
||||
val getKotlin = kotlinSourceSetIface?.methods?.find { it.name == "getKotlin" } ?: return null
|
||||
return getKotlin(convention) as? SourceDirectorySet
|
||||
}
|
||||
private fun getKotlinSourceSetsSafe(project: Project): NamedDomainObjectCollection<out Named> {
|
||||
// Access through reflection, because another project's KotlinProjectExtension might be loaded by a different class loader:
|
||||
val kotlinExt = project.extensions.getByName("kotlin")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sourceSets = kotlinExt.javaClass.getMethod("getSourceSets").invoke(kotlinExt) as NamedDomainObjectCollection<out Named>
|
||||
return sourceSets
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
protected fun <T> Project.whenEvaluated(fn: Project.() -> T) {
|
||||
if (state.executed) {
|
||||
fn()
|
||||
}
|
||||
else {
|
||||
afterEvaluate { it.fn() }
|
||||
}
|
||||
}
|
||||
protected fun getKotlinSourceDirectorySetSafe(from: Any): SourceDirectorySet? {
|
||||
val getKotlin = from.javaClass.getMethod("getKotlin")
|
||||
return getKotlin(from) as? SourceDirectorySet
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> Project.whenEvaluated(fn: Project.() -> T) {
|
||||
if (state.executed) {
|
||||
fn()
|
||||
}
|
||||
else {
|
||||
afterEvaluate { it.fn() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,11 +194,12 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
override fun namedSourceSetsContainer(project: Project): NamedDomainObjectContainer<*> =
|
||||
(project.extensions.getByName("android") as BaseExtension).sourceSets
|
||||
|
||||
override fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: SourceSet, platformProject: Project) {
|
||||
override fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: Named, platformProject: Project) {
|
||||
val androidExtension = platformProject.extensions.getByName("android") as BaseExtension
|
||||
val androidSourceSet = androidExtension.sourceSets.findByName(commonSourceSet.name) ?: return
|
||||
val kotlinSourceSet = androidSourceSet.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: return
|
||||
kotlinSourceSet.kotlin.source(commonSourceSet.kotlin!!)
|
||||
val kotlinSourceSet = androidSourceSet.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet
|
||||
?: return
|
||||
kotlinSourceSet.kotlin.source(getKotlinSourceDirectorySetSafe(commonSourceSet)!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +215,4 @@ open class KotlinPlatformJsPlugin : KotlinPlatformImplementationPluginBase("js")
|
||||
project.applyPlugin<Kotlin2JsPluginWrapper>()
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
private val Project.sourceSets: SourceSetContainer
|
||||
get() = convention.getPlugin(JavaPluginConvention::class.java).sourceSets
|
||||
}
|
||||
+393
-274
@@ -5,7 +5,6 @@ import com.android.build.gradle.BasePlugin
|
||||
import com.android.builder.model.SourceProvider
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ExternalDependency
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
@@ -13,7 +12,6 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.plugins.InvalidPluginException
|
||||
import org.gradle.api.plugins.JavaBasePlugin
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.CompileClasspathNormalizer
|
||||
@@ -26,11 +24,15 @@ 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
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedClassesDir
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage
|
||||
import org.jetbrains.kotlin.gradle.model.builder.KotlinModelBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
@@ -47,58 +49,90 @@ val KOTLIN_JS_DSL_NAME = "kotlin2js"
|
||||
val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions"
|
||||
|
||||
internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
val project: Project,
|
||||
val javaBasePlugin: JavaBasePlugin,
|
||||
val sourceSet: SourceSet,
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
val dslExtensionName: String,
|
||||
val compileTaskNameSuffix: String,
|
||||
val taskDescription: String
|
||||
val project: Project,
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val taskDescription: String,
|
||||
val kotlinCompilation: KotlinCompilation
|
||||
) {
|
||||
abstract protected fun doTargetSpecificProcessing()
|
||||
protected val logger = Logging.getLogger(this.javaClass)!!
|
||||
|
||||
protected val isSeparateClassesDirSupported: Boolean by lazy {
|
||||
!CopyClassesToJavaOutputStatus.isEnabled(project) &&
|
||||
sourceSet.output.javaClass.methods.any { it.name == "getClassesDirs" }
|
||||
kotlinCompilation.output.javaClass.methods.any { it.name == "getClassesDirs" }
|
||||
}
|
||||
|
||||
protected val sourceSetName: String = sourceSet.name
|
||||
protected val sourceRootDir: String = "src/$sourceSetName/kotlin"
|
||||
protected val kotlinSourceSet: KotlinSourceSet = createKotlinSourceSet()
|
||||
protected val sourceSetName: String = kotlinCompilation.compilationName
|
||||
|
||||
protected val kotlinTask: T = createKotlinCompileTask()
|
||||
|
||||
protected open val defaultKotlinDestinationDir: File
|
||||
get() = if (isSeparateClassesDirSupported)
|
||||
File(project.buildDir, "classes/kotlin/${sourceSet.name}") else
|
||||
sourceSet.output.classesDir
|
||||
get() {
|
||||
return if (isSeparateClassesDirSupported) {
|
||||
val kotlinExt = project.kotlinExtension
|
||||
val targetSubDirectory =
|
||||
if (kotlinExt is KotlinSingleJavaTargetExtension)
|
||||
"" // In single-target projects, don't add the target name part to this path
|
||||
else
|
||||
kotlinCompilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}")
|
||||
} else {
|
||||
kotlinCompilation.output.classesDir
|
||||
}
|
||||
}
|
||||
|
||||
fun run() {
|
||||
addKotlinDirSetToSources()
|
||||
private fun createKotlinCompileTask(): T {
|
||||
val name = kotlinCompilation.compileKotlinTaskName
|
||||
logger.kotlinDebug("Creating kotlin compile task $name")
|
||||
val kotlinCompile = doCreateTask(project, name)
|
||||
kotlinCompile.description = taskDescription
|
||||
kotlinCompile.mapClasspath { kotlinCompilation.compileDependencyFiles }
|
||||
kotlinCompile.setDestinationDir { defaultKotlinDestinationDir }
|
||||
kotlinCompilation.output.tryAddClassesDir { project.files(kotlinTask.destinationDir).builtBy(kotlinTask) }
|
||||
return kotlinCompile
|
||||
}
|
||||
|
||||
open fun run() {
|
||||
doTargetSpecificProcessing()
|
||||
}
|
||||
|
||||
private fun createKotlinSourceSet(): KotlinSourceSet {
|
||||
logger.kotlinDebug("Creating KotlinSourceSet for $sourceSet")
|
||||
val kotlinSourceSet = kotlinSourceSetProvider.create(sourceSet.name)
|
||||
kotlinSourceSet.kotlin.srcDir(project.file(sourceRootDir))
|
||||
sourceSet.addConvention(dslExtensionName, kotlinSourceSet)
|
||||
return kotlinSourceSet
|
||||
protected abstract fun doCreateTask(project: Project, taskName: String): T
|
||||
}
|
||||
|
||||
internal abstract class KotlinJavaSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
taskDescription: String,
|
||||
val javaSourceSet: SourceSet?,
|
||||
kotlinCompilation: KotlinCompilation
|
||||
): KotlinSourceSetProcessor<T>(
|
||||
project, tasksProvider, taskDescription, kotlinCompilation
|
||||
) {
|
||||
override fun run() {
|
||||
addKotlinDirSetToSources()
|
||||
super.run()
|
||||
}
|
||||
|
||||
private fun addKotlinDirSetToSources() {
|
||||
val kotlinDirSet = kotlinSourceSet.kotlin
|
||||
if (javaSourceSet == null)
|
||||
return
|
||||
|
||||
val kotlinDirSets = kotlinCompilation.kotlinSourceSets.map(KotlinSourceSet::kotlin)
|
||||
|
||||
// Try to avoid duplicate Java sources in allSource:
|
||||
val kotlinSrcDirsToAdd = filterOutJavaSrcDirsIfPossible(kotlinDirSet)
|
||||
val kotlinSrcDirsToAdd = kotlinDirSets.map { filterOutJavaSrcDirsIfPossible(it) }
|
||||
|
||||
sourceSet.allJava.srcDirs(kotlinSrcDirsToAdd)
|
||||
sourceSet.allSource.srcDirs(kotlinSrcDirsToAdd)
|
||||
sourceSet.resources.filter.exclude { it.file in kotlinDirSet }
|
||||
kotlinSrcDirsToAdd.forEach { kotlinSrcDirs ->
|
||||
javaSourceSet.allJava.srcDirs(kotlinSrcDirs)
|
||||
javaSourceSet.allSource.srcDirs(kotlinSrcDirs)
|
||||
javaSourceSet.resources.filter.exclude { it.file in kotlinSrcDirs }
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterOutJavaSrcDirsIfPossible(sourceDirectorySet: SourceDirectorySet): FileCollection {
|
||||
if (javaSourceSet == null)
|
||||
return sourceDirectorySet
|
||||
|
||||
// If the API used below is not available, fall back to not filtering the Java sources.
|
||||
if (SourceDirectorySet::class.java.methods.none { it.name == "getSourceDirectories" }) {
|
||||
return sourceDirectorySet
|
||||
@@ -110,35 +144,19 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
}
|
||||
|
||||
// Build a lazily-resolved file collection that filters out Java sources from sources of this sourceDirectorySet
|
||||
return getSourceDirectories(sourceDirectorySet).minus(getSourceDirectories(sourceSet.java))
|
||||
return getSourceDirectories(sourceDirectorySet).minus(getSourceDirectories(javaSourceSet.java))
|
||||
}
|
||||
|
||||
private fun createKotlinCompileTask(): T {
|
||||
val name = sourceSet.getCompileTaskName(compileTaskNameSuffix)
|
||||
logger.kotlinDebug("Creating kotlin compile task $name")
|
||||
val kotlinCompile = doCreateTask(project, name)
|
||||
kotlinCompile.description = taskDescription
|
||||
kotlinCompile.mapClasspath { sourceSet.compileClasspath }
|
||||
kotlinCompile.setDestinationDir { defaultKotlinDestinationDir }
|
||||
sourceSet.output.tryAddClassesDir { project.files(kotlinTask.destinationDir).builtBy(kotlinTask) }
|
||||
return kotlinCompile
|
||||
}
|
||||
|
||||
protected abstract fun doCreateTask(project: Project, taskName: String): T
|
||||
}
|
||||
|
||||
internal class Kotlin2JvmSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<KotlinCompile>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_DSL_NAME,
|
||||
compileTaskNameSuffix = "kotlin",
|
||||
taskDescription = "Compiles the $sourceSet.kotlin."
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinCompilation: KotlinCompilation,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinJavaSourceSetProcessor<KotlinCompile>(
|
||||
project, tasksProvider, taskDescription = "Compiles the $kotlinCompilation.",
|
||||
javaSourceSet = if (kotlinCompilation is KotlinWithJavaCompilation) kotlinCompilation.javaSourceSet else null,
|
||||
kotlinCompilation = kotlinCompilation
|
||||
) {
|
||||
override val defaultKotlinDestinationDir: File
|
||||
get() = if (!isSeparateClassesDirSupported)
|
||||
@@ -146,44 +164,38 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
super.defaultKotlinDestinationDir
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompile =
|
||||
tasksProvider.createKotlinJVMTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinJVMTask(project, taskName, kotlinCompilation.compilationName)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
kotlinSourceSet.kotlin.source(sourceSet.java)
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, sourceSet.name)
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, kotlinCompilation.compilationName)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
if (project != null) {
|
||||
val javaTask = project.tasks.findByName(sourceSet.compileJavaTaskName)
|
||||
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
|
||||
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask as JavaCompile, null, null, sourceSet)
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
// KotlinCompile.source(kotlinDirSet) should be called only after all java roots are added to kotlinDirSet
|
||||
// otherwise some java roots can be ignored
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { plugin -> kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> plugin.source(sourceSet.kotlin) } }
|
||||
|
||||
configureJavaTask(kotlinTask, javaTask, logger)
|
||||
javaTask?.let { configureJavaTask(kotlinTask, it, logger) }
|
||||
|
||||
var syncOutputTask: SyncOutputTask? = null
|
||||
var syncOutputTask: SyncOutputTask? = null
|
||||
|
||||
if (!isSeparateClassesDirSupported) {
|
||||
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
|
||||
}
|
||||
|
||||
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
val (classesProviderTask, classesDirectory) = when {
|
||||
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
|
||||
else -> syncOutputTask!!.let { it to it.javaOutputDir }
|
||||
}
|
||||
|
||||
registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask)
|
||||
if (!isSeparateClassesDirSupported && javaTask != null) {
|
||||
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
|
||||
}
|
||||
|
||||
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
val (classesProviderTask, classesDirectory) = when {
|
||||
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
|
||||
else -> syncOutputTask!!.let { it to it.javaOutputDir }
|
||||
}
|
||||
|
||||
registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,37 +245,35 @@ internal fun SourceSetOutput.tryAddClassesDir(
|
||||
}
|
||||
|
||||
internal class Kotlin2JsSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinCompilation: KotlinCompilation,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_JS_DSL_NAME,
|
||||
taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.",
|
||||
compileTaskNameSuffix = "kotlin2Js"
|
||||
project, tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
|
||||
kotlinCompilation = kotlinCompilation
|
||||
) {
|
||||
override fun doCreateTask(project: Project, taskName: String): Kotlin2JsCompile =
|
||||
tasksProvider.createKotlinJSTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinJSTask(project, taskName, kotlinCompilation.compilationName)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
project.tasks.findByName(sourceSet.classesTaskName)!!.dependsOn(kotlinTask)
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
|
||||
createCleanSourceMapTask()
|
||||
|
||||
sourceSet.clearJavaSrcDirs()
|
||||
if (kotlinCompilation is KotlinWithJavaCompilation) {
|
||||
kotlinCompilation.javaSourceSet.clearJavaSrcDirs()
|
||||
}
|
||||
|
||||
// outputFile can be set later during the configuration phase, get it only after the phase:
|
||||
project.afterEvaluate { project ->
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, kotlinTask, null, null, sourceSet)
|
||||
|
||||
kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath
|
||||
val outputDir = kotlinTask.outputFile.parentFile
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, null, null, null, kotlinCompilation)
|
||||
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTask) contains or " +
|
||||
@@ -274,17 +284,17 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
kotlinTask.destinationDir = outputDir
|
||||
|
||||
if (!isSeparateClassesDirSupported) {
|
||||
sourceSet.output.setClassesDirCompatible(kotlinTask.destinationDir)
|
||||
kotlinCompilation.output.setClassesDirCompatible(kotlinTask.destinationDir)
|
||||
}
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
.forEach { task -> kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCleanSourceMapTask() {
|
||||
val taskName = sourceSet.getTaskName("clean", "sourceMap")
|
||||
val taskName = kotlinCompilation.composeName("clean", "sourceMap")
|
||||
val task = project.tasks.create(taskName, Delete::class.java)
|
||||
task.onlyIf { kotlinTask.kotlinOptions.sourceMap }
|
||||
task.delete(object : Closure<String>(this) {
|
||||
@@ -295,189 +305,274 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
}
|
||||
|
||||
internal class KotlinCommonSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<KotlinCompileCommon>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_DSL_NAME,
|
||||
taskDescription = "Compiles the kotlin sources in $sourceSet to Metadata.",
|
||||
compileTaskNameSuffix = "kotlinCommon"
|
||||
project, tasksProvider, taskDescription = "Compiles the kotlin sources in $compilation to Metadata.",
|
||||
kotlinCompilation = compilation
|
||||
) {
|
||||
override fun doTargetSpecificProcessing() {
|
||||
sourceSet.clearJavaSrcDirs()
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
// can be missing (e.g. in case of tests)
|
||||
if (kotlinCompilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||
project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
|
||||
}
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, kotlinTask, null, null, sourceSet)
|
||||
|
||||
project.tasks.findByName(sourceSet.classesTaskName)!!.dependsOn(kotlinTask)
|
||||
// can be missing (e.g. in case of tests)
|
||||
project.tasks.findByName(sourceSet.jarTaskName)?.dependsOn(kotlinTask)
|
||||
|
||||
project, kotlinTask, null, null, null, kotlinCompilation
|
||||
)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> it.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompileCommon =
|
||||
tasksProvider.createKotlinCommonTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinCommonTask(project, taskName, kotlinCompilation.compilationName)
|
||||
}
|
||||
|
||||
|
||||
internal abstract class AbstractKotlinPlugin(
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
protected val kotlinPluginVersion: String,
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
protected val kotlinPluginVersion: String,
|
||||
val registry: ToolingModelBuilderRegistry
|
||||
) : Plugin<Project> {
|
||||
internal abstract fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String): KotlinSourceSetProcessor<*>
|
||||
|
||||
internal abstract fun buildSourceSetProcessor(project: Project, compilation: KotlinCompilation, kotlinPluginVersion: String): KotlinSourceSetProcessor<*>
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val javaBasePlugin = project.plugins.apply(JavaBasePlugin::class.java)
|
||||
val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java)
|
||||
|
||||
project.plugins.apply(JavaPlugin::class.java)
|
||||
|
||||
configureSourceSetDefaults(project, javaBasePlugin, javaPluginConvention)
|
||||
configureDefaultVersionsResolutionStrategy(project)
|
||||
configureClassInspectionForIC(project)
|
||||
configureTarget(
|
||||
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target,
|
||||
{ compilation -> buildSourceSetProcessor(project, compilation, kotlinPluginVersion) }
|
||||
)
|
||||
|
||||
configureProjectGlobalSettings(project, kotlinPluginVersion)
|
||||
registry.register(KotlinModelBuilder(kotlinPluginVersion))
|
||||
}
|
||||
|
||||
open protected fun configureSourceSetDefaults(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
javaPluginConvention: JavaPluginConvention
|
||||
) {
|
||||
javaPluginConvention.sourceSets?.all { sourceSet ->
|
||||
buildSourceSetProcessor(project, javaBasePlugin, sourceSet, kotlinPluginVersion).run()
|
||||
}
|
||||
companion object {
|
||||
fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) {
|
||||
configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion)
|
||||
configureClassInspectionForIC(project)
|
||||
}
|
||||
|
||||
private fun configureDefaultVersionsResolutionStrategy(project: Project) {
|
||||
project.configurations.all { configuration ->
|
||||
if (isGradleVersionAtLeast(4, 4)) {
|
||||
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
|
||||
configuration.withDependencies { dependencySet ->
|
||||
dependencySet.filterIsInstance<ExternalDependency>()
|
||||
.filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() }
|
||||
.forEach { it.version { constraint -> constraint.prefer(kotlinPluginVersion) } }
|
||||
}
|
||||
fun configureTarget(
|
||||
target: KotlinWithJavaTarget,
|
||||
buildSourceSetProcessor: (KotlinCompilation) -> KotlinSourceSetProcessor<*>
|
||||
) {
|
||||
setUpJavaSourceSets(target)
|
||||
configureSourceSetDefaults(target, buildSourceSetProcessor)
|
||||
}
|
||||
|
||||
private fun configureClassInspectionForIC(project: Project) {
|
||||
val classesTask = project.tasks.findByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
val jarTask = project.tasks.findByName(JavaPlugin.JAR_TASK_NAME)
|
||||
|
||||
if (classesTask == null || jarTask !is Jar) {
|
||||
project.logger.info(
|
||||
"Could not configure class inspection task " +
|
||||
"(classes task = ${classesTask?.javaClass?.canonicalName}, " +
|
||||
"jar task = ${classesTask?.javaClass?.canonicalName}"
|
||||
)
|
||||
return
|
||||
}
|
||||
else {
|
||||
configuration.resolutionStrategy.eachDependency { details ->
|
||||
val requested = details.requested
|
||||
if (requested.group == "org.jetbrains.kotlin" && requested.version.isEmpty()) {
|
||||
details.useVersion(kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
}
|
||||
|
||||
private fun setUpJavaSourceSets(
|
||||
kotlinTarget: KotlinWithJavaTarget
|
||||
) {
|
||||
val project = kotlinTarget.project
|
||||
val javaSourceSets = project.convention.getPlugin(JavaPluginConvention::class.java).sourceSets
|
||||
|
||||
val kotlinSourceSetDslName = when (kotlinTarget.platformType) {
|
||||
KotlinPlatformType.js -> KOTLIN_JS_DSL_NAME
|
||||
else -> KOTLIN_DSL_NAME
|
||||
}
|
||||
|
||||
// Workaround for indirect mutual recursion between the two `all { ... }` handlers:
|
||||
val compilationsUnderConstruction = mutableMapOf<String, KotlinWithJavaCompilation>()
|
||||
|
||||
javaSourceSets.all { javaSourceSet ->
|
||||
val kotlinCompilation = compilationsUnderConstruction[javaSourceSet.name] ?: kotlinTarget.compilations.maybeCreate(javaSourceSet.name)
|
||||
kotlinCompilation.javaSourceSet = javaSourceSet
|
||||
val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate(kotlinCompilation.name)
|
||||
javaSourceSet.addConvention(kotlinSourceSetDslName, kotlinSourceSet)
|
||||
kotlinSourceSet.kotlin.source(javaSourceSet.java)
|
||||
kotlinCompilation.source(kotlinSourceSet)
|
||||
}
|
||||
|
||||
kotlinTarget.compilations.all { kotlinCompilation ->
|
||||
val sourceSetName = kotlinCompilation.name
|
||||
compilationsUnderConstruction[sourceSetName] = kotlinCompilation
|
||||
kotlinCompilation.javaSourceSet = javaSourceSets.maybeCreate(sourceSetName)
|
||||
|
||||
// Another Kotlin source set following the other convention, named according to the compilation, not the Java source set:
|
||||
val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate(kotlinCompilation.fullName)
|
||||
kotlinCompilation.source(kotlinSourceSet)
|
||||
}
|
||||
}
|
||||
|
||||
fun configureSourceSetDefaults(
|
||||
kotlinTarget: KotlinTarget,
|
||||
buildSourceSetProcessor: (KotlinCompilation) -> KotlinSourceSetProcessor<*>
|
||||
) {
|
||||
kotlinTarget.compilations.all { compilation ->
|
||||
buildSourceSetProcessor(compilation).run()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureClassInspectionForIC(project: Project) {
|
||||
val classesTask = project.tasks.findByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
val jarTask = project.tasks.findByName(JavaPlugin.JAR_TASK_NAME)
|
||||
|
||||
if (classesTask == null || jarTask !is Jar) {
|
||||
project.logger.info(
|
||||
"Could not configure class inspection task " +
|
||||
"(classes task = ${classesTask?.javaClass?.canonicalName}, " +
|
||||
"jar task = ${classesTask?.javaClass?.canonicalName}"
|
||||
)
|
||||
return
|
||||
internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) {
|
||||
project.configurations.all { configuration ->
|
||||
if (isGradleVersionAtLeast(4, 4)) {
|
||||
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
|
||||
configuration.withDependencies { dependencySet ->
|
||||
dependencySet.filterIsInstance<ExternalDependency>()
|
||||
.filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() }
|
||||
.forEach { it.version { constraint -> constraint.prefer(kotlinPluginVersion) } }
|
||||
}
|
||||
} else {
|
||||
configuration.resolutionStrategy.eachDependency { details ->
|
||||
val requested = details.requested
|
||||
if (requested.group == "org.jetbrains.kotlin" && requested.version.isEmpty()) {
|
||||
details.useVersion(kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
kotlinPluginVersion: String,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String,
|
||||
registry: ToolingModelBuilderRegistry
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, registry) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion, registry) {
|
||||
|
||||
override fun buildSourceSetProcessor(project: Project, compilation: KotlinCompilation, kotlinPluginVersion: String) =
|
||||
Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.jvm, "").apply {
|
||||
disambiguationClassifier = null // don't add anything to the task names
|
||||
}
|
||||
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target
|
||||
|
||||
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinCommonPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
kotlinPluginVersion: String,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String,
|
||||
registry: ToolingModelBuilderRegistry
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, registry) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
KotlinCommonSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
}
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion, registry) {
|
||||
|
||||
internal open class Kotlin2JsPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
kotlinPluginVersion: String,
|
||||
registry: ToolingModelBuilderRegistry
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, registry) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
Kotlin2JsSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
}
|
||||
|
||||
internal open class KotlinAndroidPlugin(
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : Plugin<Project> {
|
||||
override fun buildSourceSetProcessor(
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
kotlinPluginVersion: String
|
||||
): KotlinSourceSetProcessor<*> =
|
||||
KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val version = loadAndroidPluginVersion()
|
||||
if (version != null) {
|
||||
val minimalVersion = "1.1.0"
|
||||
if (compareVersionNumbers(version, minimalVersion) < 0) {
|
||||
throw IllegalStateException("Kotlin: Unsupported version of com.android.tools.build:gradle plugin: version $minimalVersion or higher should be used with kotlin-android plugin")
|
||||
}
|
||||
}
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.common, "common")
|
||||
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target
|
||||
|
||||
val kotlinTools = KotlinConfigurationTools(
|
||||
kotlinSourceSetProvider,
|
||||
tasksProvider,
|
||||
kotlinPluginVersion)
|
||||
|
||||
val legacyVersionThreshold = "2.5.0"
|
||||
|
||||
val variantProcessor = if (compareVersionNumbers(version, legacyVersionThreshold) < 0) {
|
||||
LegacyAndroidAndroidProjectHandler(kotlinTools)
|
||||
}
|
||||
else {
|
||||
val android25ProjectHandlerClass = Class.forName("org.jetbrains.kotlin.gradle.plugin.Android25ProjectHandler")
|
||||
val ctor = android25ProjectHandlerClass.constructors.single {
|
||||
it.parameterTypes.contentEquals(arrayOf(kotlinTools.javaClass))
|
||||
}
|
||||
ctor.newInstance(kotlinTools) as AbstractAndroidProjectHandler<*>
|
||||
}
|
||||
|
||||
variantProcessor.handleProject(project)
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinConfigurationTools internal constructor(val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
val kotlinTasksProvider: KotlinTasksProvider,
|
||||
val kotlinPluginVersion: String)
|
||||
internal open class Kotlin2JsPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String,
|
||||
registry: ToolingModelBuilderRegistry
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion, registry) {
|
||||
|
||||
override fun buildSourceSetProcessor(
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
kotlinPluginVersion: String
|
||||
): KotlinSourceSetProcessor<*> =
|
||||
Kotlin2JsSourceSetProcessor(
|
||||
project, tasksProvider, compilation, kotlinPluginVersion
|
||||
)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.js, "2Js")
|
||||
|
||||
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinAndroidPlugin(
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : Plugin<Project> {
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val androidTarget = KotlinAndroidTarget("", project)
|
||||
|
||||
applyToTarget(
|
||||
project, androidTarget, tasksProvider,
|
||||
kotlinPluginVersion
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun applyToTarget(
|
||||
project: Project,
|
||||
kotlinTarget: KotlinAndroidTarget,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String
|
||||
) {
|
||||
|
||||
val version = loadAndroidPluginVersion()
|
||||
if (version != null) {
|
||||
val minimalVersion = "1.1.0"
|
||||
if (compareVersionNumbers(version, minimalVersion) < 0) {
|
||||
throw IllegalStateException("Kotlin: Unsupported version of com.android.tools.build:gradle plugin: version $minimalVersion or higher should be used with kotlin-android plugin")
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinTools = KotlinConfigurationTools(
|
||||
tasksProvider,
|
||||
kotlinPluginVersion
|
||||
)
|
||||
|
||||
val legacyVersionThreshold = "2.5.0"
|
||||
|
||||
val variantProcessor = if (compareVersionNumbers(version, legacyVersionThreshold) < 0) {
|
||||
LegacyAndroidAndroidProjectHandler(kotlinTools)
|
||||
} else {
|
||||
val android25ProjectHandlerClass = Class.forName("org.jetbrains.kotlin.gradle.plugin.Android25ProjectHandler")
|
||||
val ctor = android25ProjectHandlerClass.constructors.single {
|
||||
it.parameterTypes.contentEquals(arrayOf(kotlinTools.javaClass))
|
||||
}
|
||||
ctor.newInstance(kotlinTools) as AbstractAndroidProjectHandler<*>
|
||||
}
|
||||
|
||||
variantProcessor.handleProject(project, kotlinTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinConfigurationTools internal constructor(
|
||||
val kotlinTasksProvider: KotlinTasksProvider,
|
||||
val kotlinPluginVersion: String
|
||||
)
|
||||
|
||||
/** Part of Android configuration, that works only with the old public API.
|
||||
* @see [LegacyAndroidAndroidProjectHandler] that is implemented with the old internal API and [AndroidGradle25VariantProcessor] that works
|
||||
@@ -497,18 +592,22 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
|
||||
protected open fun checkVariantIsValid(variant: V) = Unit
|
||||
|
||||
protected abstract fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: V,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile)
|
||||
protected open fun setUpDependencyResolution(variant: V, compilation: KotlinJvmAndroidCompilation) = Unit
|
||||
|
||||
protected abstract fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: V,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
)
|
||||
|
||||
protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData<V>
|
||||
|
||||
fun handleProject(project: Project) {
|
||||
fun handleProject(project: Project, kotlinAndroidTarget: KotlinAndroidTarget) {
|
||||
val ext = project.extensions.getByName("android") as BaseExtension
|
||||
val aptConfigurations = hashMapOf<String, Configuration>()
|
||||
|
||||
ext.sourceSets.all { sourceSet ->
|
||||
logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet")
|
||||
@@ -527,42 +626,49 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
ext.addExtension(KOTLIN_OPTIONS_DSL_NAME, kotlinOptions)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
if (project != null) {
|
||||
val androidPluginIds = listOf("android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature", "com.android.instantapp")
|
||||
val plugin = androidPluginIds.asSequence()
|
||||
.mapNotNull { project.plugins.findPlugin(it) as? BasePlugin }
|
||||
.firstOrNull()
|
||||
?: throw InvalidPluginException("'kotlin-android' expects one of the Android Gradle " +
|
||||
"plugins to be applied to the project:\n\t" +
|
||||
androidPluginIds.joinToString("\n\t") { "* $it" })
|
||||
val androidPluginIds = listOf("android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature", "com.android.instantapp")
|
||||
val plugin = androidPluginIds.asSequence()
|
||||
.mapNotNull { project.plugins.findPlugin(it) as? BasePlugin }
|
||||
.firstOrNull()
|
||||
?: throw InvalidPluginException("'kotlin-android' expects one of the Android Gradle " +
|
||||
"plugins to be applied to the project:\n\t" +
|
||||
androidPluginIds.joinToString("\n\t") { "* $it" })
|
||||
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
|
||||
|
||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||
|
||||
forEachVariant(project) {
|
||||
processVariant(it, project, ext, plugin, aptConfigurations, kotlinOptions,
|
||||
kotlinConfigurationTools.kotlinTasksProvider, subpluginEnvironment)
|
||||
}
|
||||
forEachVariant(project) {
|
||||
processVariant(
|
||||
it, kotlinAndroidTarget, project, ext, plugin, kotlinOptions, kotlinConfigurationTools.kotlinTasksProvider,
|
||||
subpluginEnvironment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processVariant(variantData: V,
|
||||
project: Project,
|
||||
androidExt: BaseExtension,
|
||||
androidPlugin: BasePlugin,
|
||||
aptConfigurations: Map<String, Configuration>,
|
||||
rootKotlinOptions: KotlinJvmOptionsImpl,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
subpluginEnvironment: SubpluginEnvironment) {
|
||||
private fun processVariant(
|
||||
variantData: V,
|
||||
target: KotlinAndroidTarget,
|
||||
project: Project,
|
||||
androidExt: BaseExtension,
|
||||
androidPlugin: BasePlugin,
|
||||
rootKotlinOptions: KotlinJvmOptionsImpl,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
subpluginEnvironment: SubpluginEnvironment
|
||||
) {
|
||||
|
||||
checkVariantIsValid(variantData)
|
||||
|
||||
val variantDataName = getVariantName(variantData)
|
||||
logger.kotlinDebug("Process variant [$variantDataName]")
|
||||
|
||||
val compilation = target.compilations.create(variantDataName).apply {
|
||||
KotlinTargetConfigurator.defineConfigurationsForCompilation(this, target, project.configurations)
|
||||
}
|
||||
|
||||
setUpDependencyResolution(variantData, compilation)
|
||||
|
||||
val javaTask = getJavaTask(variantData)
|
||||
|
||||
if (javaTask == null) {
|
||||
@@ -570,7 +676,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
return
|
||||
}
|
||||
|
||||
val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin"
|
||||
val kotlinTaskName = compilation.compileKotlinTaskName
|
||||
// todo: Investigate possibility of creating and configuring kotlinTask before evaluation
|
||||
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName, variantDataName)
|
||||
kotlinTask.parentKotlinOptionsImpl = rootKotlinOptions
|
||||
@@ -579,22 +685,35 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
|
||||
kotlinTask.description = "Compiles the $variantDataName kotlin."
|
||||
|
||||
configureSources(kotlinTask, variantData)
|
||||
wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
configureSources(kotlinTask, variantData, compilation)
|
||||
|
||||
// In MPPs, add the common main Kotlin sources to non-test variants, the common test sources to test variants
|
||||
val commonSourceSetName = if (getTestedVariantData(variantData) == null)
|
||||
KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME else
|
||||
KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME
|
||||
project.kotlinExtension.sourceSets.findByName(commonSourceSetName)?.let {
|
||||
compilation.source(it)
|
||||
}
|
||||
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), this, null)
|
||||
|
||||
appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { configureSources(it, variantData) }
|
||||
.forEach { configureSources(it, variantData, null) }
|
||||
}
|
||||
|
||||
private fun configureSources(compileTask: AbstractCompile, variantData: V) {
|
||||
private fun configureSources(compileTask: AbstractCompile, variantData: V, compilation: KotlinCompilation?) {
|
||||
val logger = compileTask.project.logger
|
||||
|
||||
for (provider in getSourceProviders(variantData)) {
|
||||
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
|
||||
compileTask.source(kotlinSourceSet.kotlin)
|
||||
if (compilation != null) {
|
||||
compilation.source(kotlinSourceSet)
|
||||
} else {
|
||||
compileTask.source(kotlinSourceSet.kotlin)
|
||||
}
|
||||
}
|
||||
|
||||
for (javaSrcDir in getAllJavaSources(variantData)) {
|
||||
@@ -696,10 +815,10 @@ internal class SubpluginEnvironment(
|
||||
fun <C: CommonCompilerArguments> addSubpluginOptions(
|
||||
project: Project,
|
||||
kotlinTask: AbstractKotlinCompile<C>,
|
||||
javaTask: AbstractCompile,
|
||||
javaTask: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>?,
|
||||
javaSourceSet: SourceSet?
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> {
|
||||
val pluginOptions = kotlinTask.pluginOptions
|
||||
|
||||
@@ -716,7 +835,7 @@ internal class SubpluginEnvironment(
|
||||
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, javaSourceSet)
|
||||
val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation)
|
||||
val subpluginId = subplugin.getCompilerPluginId()
|
||||
kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
|
||||
|
||||
|
||||
+47
-20
@@ -21,11 +21,14 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
|
||||
import org.gradle.internal.reflect.Instantiator
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.createKotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetProviderImpl
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinSourceSetFactory
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.FileNotFoundException
|
||||
@@ -33,7 +36,9 @@ import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver): Plugin<Project> {
|
||||
abstract class KotlinBasePluginWrapper(
|
||||
protected val fileResolver: FileResolver
|
||||
): Plugin<Project> {
|
||||
private val log = Logging.getLogger(this.javaClass)
|
||||
val kotlinPluginVersion = loadKotlinVersionFromResource(log)
|
||||
|
||||
@@ -66,32 +71,54 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver)
|
||||
plugin.apply(project)
|
||||
}
|
||||
|
||||
internal abstract fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project>
|
||||
|
||||
open val projectExtensionClass: KClass<out KotlinProjectExtension> get() = KotlinProjectExtension::class
|
||||
internal abstract fun getPlugin(
|
||||
project: Project,
|
||||
kotlinGradleBuildServices: KotlinGradleBuildServices
|
||||
): Plugin<Project>
|
||||
}
|
||||
|
||||
open class KotlinPluginWrapper @Inject internal constructor(fileResolver: FileResolver, protected val registry: ToolingModelBuilderRegistry): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinPlugin(KotlinTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, registry)
|
||||
open class KotlinPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
protected val registry: ToolingModelBuilderRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinPlugin(KotlinTasksProvider(), kotlinPluginVersion, registry)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinJvmProjectExtension>
|
||||
get() = KotlinJvmProjectExtension::class
|
||||
}
|
||||
|
||||
open class KotlinCommonPluginWrapper @Inject internal constructor(fileResolver: FileResolver, protected val registry: ToolingModelBuilderRegistry): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinCommonPlugin(KotlinCommonTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, registry)
|
||||
open class KotlinCommonPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
protected val registry: ToolingModelBuilderRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinCommonPlugin(KotlinCommonTasksProvider(), kotlinPluginVersion, registry)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinSingleJavaTargetExtension>
|
||||
get() = KotlinSingleJavaTargetExtension::class
|
||||
}
|
||||
|
||||
open class KotlinAndroidPluginWrapper @Inject internal constructor(fileResolver: FileResolver, protected val registry: ToolingModelBuilderRegistry): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion)
|
||||
open class KotlinAndroidPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
protected val registry: ToolingModelBuilderRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinAndroidPlugin(
|
||||
AndroidTasksProvider(),
|
||||
kotlinPluginVersion
|
||||
)
|
||||
}
|
||||
|
||||
open class Kotlin2JsPluginWrapper @Inject internal constructor(fileResolver: FileResolver, protected val registry: ToolingModelBuilderRegistry): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
Kotlin2JsPlugin(Kotlin2JsTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, registry)
|
||||
open class Kotlin2JsPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
protected val registry: ToolingModelBuilderRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
Kotlin2JsPlugin(Kotlin2JsTasksProvider(), kotlinPluginVersion, registry)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinSingleJavaTargetExtension>
|
||||
get() = KotlinSingleJavaTargetExtension::class
|
||||
}
|
||||
|
||||
fun Project.getKotlinPluginVersion(): String? =
|
||||
|
||||
+9
-6
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.gradle.internal.KaptTask
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.internal.registerGeneratedJavaSource
|
||||
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.checkedReflection
|
||||
import java.io.File
|
||||
@@ -40,12 +41,14 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
|
||||
variantManager.variantDataList.forEach(action)
|
||||
}
|
||||
|
||||
override fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariantData<out BaseVariantOutputData>,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
override fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariantData<out BaseVariantOutputData>,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
) {
|
||||
kotlinTask.dependsOn(*javaTask.dependsOn.toTypedArray())
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import java.util.*
|
||||
|
||||
// TODO better implementation: attribute invariants (no attrs with same name and different types allowed), thread safety?
|
||||
class HierarchyAttributeContainer(val parent: AttributeContainer?) : AttributeContainer {
|
||||
private val attributesMap = Collections.synchronizedMap(mutableMapOf<Attribute<*>, Any>())
|
||||
|
||||
override fun contains(key: Attribute<*>): Boolean =
|
||||
attributesMap.contains(key) || parent?.contains(key) ?: false
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any?> getAttribute(key: Attribute<T>?): T? =
|
||||
attributesMap.get(key as Attribute<*>) as T? ?: parent?.getAttribute(key)
|
||||
|
||||
override fun isEmpty(): Boolean = attributesMap.isEmpty() && parent?.isEmpty ?: false
|
||||
|
||||
override fun keySet(): Set<Attribute<*>> = attributesMap.keys + parent?.keySet().orEmpty()
|
||||
|
||||
override fun <T : Any?> attribute(key: Attribute<T>?, value: T): AttributeContainer {
|
||||
val checkedValue = requireNotNull(value as Any?) { "null values for attributes are not supported" }
|
||||
attributesMap[key as Attribute<*>] = checkedValue
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getAttributes(): AttributeContainer = this
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import org.gradle.api.NamedDomainObjectFactory
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
|
||||
interface KotlinCompilationFactory<T: KotlinCompilation> : NamedDomainObjectFactory<T> {
|
||||
val itemClass: Class<T>
|
||||
}
|
||||
|
||||
private fun KotlinTarget.createCompilationOutput(name: String) =
|
||||
KotlinCompilationOutput(project, project.buildDir.resolve("processedResources/$name"))
|
||||
|
||||
class KotlinCommonCompilationFactory(
|
||||
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||
override val itemClass: Class<KotlinCommonCompilation>
|
||||
get() = KotlinCommonCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinCommonCompilation =
|
||||
KotlinCommonCompilation(target, name, target.createCompilationOutput(name))
|
||||
}
|
||||
|
||||
class KotlinJvmCompilationFactory(
|
||||
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||
override val itemClass: Class<KotlinJvmCompilation>
|
||||
get() = KotlinJvmCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJvmCompilation =
|
||||
KotlinJvmCompilation(target, name, target.createCompilationOutput(name))
|
||||
}
|
||||
|
||||
class KotlinWithJavaCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinWithJavaTarget
|
||||
) : KotlinCompilationFactory<KotlinWithJavaCompilation> {
|
||||
|
||||
override val itemClass: Class<KotlinWithJavaCompilation>
|
||||
get() = KotlinWithJavaCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinWithJavaCompilation {
|
||||
val result = KotlinWithJavaCompilation(target, name)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmAndroidCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinAndroidTarget
|
||||
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||
|
||||
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||
get() = KotlinJvmAndroidCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||
KotlinJvmAndroidCompilation(target, name, target.createCompilationOutput(name))
|
||||
}
|
||||
|
||||
class KotlinJsCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||
override val itemClass: Class<KotlinJsCompilation>
|
||||
get() = KotlinJsCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJsCompilation =
|
||||
KotlinJsCompilation(target, name, target.createCompilationOutput(name))
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.file.FileCollectionInternal
|
||||
import org.gradle.api.internal.file.FileCollectionVisitor
|
||||
import org.gradle.api.internal.file.FileSystemSubset
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import java.io.File
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
class KotlinCompilationOutput constructor(
|
||||
private val project: Project,
|
||||
private var resourcesDir: Any,
|
||||
private var backingFileCollection: ConfigurableFileCollection = project.files() // must be a parameter since it is used in delegation
|
||||
) : SourceSetOutput, ConfigurableFileCollection by backingFileCollection, FileCollectionInternal {
|
||||
|
||||
/* TODO report Gradle bug: cannot implement SourceSetOutput without also implementing FileCollectionInternal, there's a cast to the latter
|
||||
inside the Gradle logic for resolving file collections */
|
||||
override fun registerWatchPoints(p0: FileSystemSubset.Builder) = (backingFileCollection as FileCollectionInternal).registerWatchPoints(p0)
|
||||
override fun visitRootElements(p0: FileCollectionVisitor) = (backingFileCollection as FileCollectionInternal).visitRootElements(p0)
|
||||
|
||||
private val classesDirs: FileCollection = project.files()
|
||||
private val otherDirs: ConfigurableFileCollection = project.files()
|
||||
|
||||
init {
|
||||
this.from(classesDirs)
|
||||
this.from(Callable { resourcesDir })
|
||||
}
|
||||
|
||||
override fun setResourcesDir(dirNotation: Any) {
|
||||
resourcesDir = dirNotation
|
||||
}
|
||||
|
||||
override fun setResourcesDir(dir: File): Unit = setResourcesDir(dir as Any)
|
||||
|
||||
override fun getDirs(): FileCollection = otherDirs
|
||||
|
||||
override fun isLegacyLayout(): Boolean = false
|
||||
|
||||
override fun getResourcesDir(): File = project.file(resourcesDir)
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun setClassesDir(file: File?) = @Suppress("deprecation") setClassesDir(file as Any)
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun setClassesDir(fileNotation: Any?) = throw UnsupportedOperationException("Setting classesDir is not supported, use classesDirs.")
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun getClassesDir(): File = classesDirs.singleFile
|
||||
|
||||
override fun getClassesDirs(): FileCollection = classesDirs
|
||||
|
||||
override fun dir(args: Map<String, Any>, dir: Any?) {
|
||||
val dirFileCollection = project.files(dir)
|
||||
args["builtBy"]?.let { dirFileCollection.builtBy(it) }
|
||||
otherDirs.from(dirFileCollection)
|
||||
}
|
||||
|
||||
override fun dir(dirNotation: Any?): Unit = dir(emptyMap(), dirNotation)
|
||||
}
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
|
||||
internal fun KotlinCompilation.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||
val targetNamePart = target.disambiguationClassifier
|
||||
|
||||
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||
}
|
||||
|
||||
internal val KotlinCompilation.fullName: String
|
||||
get() = fullCompilationName(target, compilationName)
|
||||
|
||||
internal fun fullCompilationName(target: KotlinTarget, simpleName: String) = lowerCamelCaseName(target.disambiguationClassifier, simpleName)
|
||||
|
||||
internal class DefaultKotlinDependencyHandler(
|
||||
val parent: HasKotlinDependencies,
|
||||
val project: Project
|
||||
) : KotlinDependencyHandler {
|
||||
override fun api(dependencyNotation: Any) = addDependency(parent.apiConfigurationName, dependencyNotation)
|
||||
|
||||
override fun implementation(dependencyNotation: Any) = addDependency(parent.implementationConfigurationName, dependencyNotation)
|
||||
|
||||
override fun compileOnly(dependencyNotation: Any) = addDependency(parent.compileOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
override fun runtimeOnly(dependencyNotation: Any) = addDependency(parent.runtimeOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
private fun addDependency(configurationName: String, dependencyNotation: Any) {
|
||||
project.dependencies.add(configurationName, dependencyNotation)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinCompilation(
|
||||
final override val target: KotlinTarget,
|
||||
override val compilationName: String
|
||||
) : KotlinCompilation, HasKotlinDependencies {
|
||||
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||
|
||||
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||
|
||||
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||
|
||||
override fun source(sourceSet: KotlinSourceSet) {
|
||||
if (kotlinSourceSets.add(sourceSet)) {
|
||||
with(target.project) {
|
||||
whenEvaluated {
|
||||
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(sourceSet.kotlin)
|
||||
}
|
||||
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName)
|
||||
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName)
|
||||
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName)
|
||||
if (this is KotlinCompilationToRunnableFiles) {
|
||||
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val compileDependencyConfigurationName: String
|
||||
get() = lowerCamelCaseName(
|
||||
target.disambiguationClassifier,
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||
"compileClasspath"
|
||||
)
|
||||
|
||||
override val compileKotlinTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
"compile",
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||
"Kotlin",
|
||||
target.targetName
|
||||
)
|
||||
|
||||
override val compileAllTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
target.disambiguationClassifier,
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||
"classes"
|
||||
)
|
||||
|
||||
override lateinit var compileDependencyFiles: FileCollection
|
||||
|
||||
override val apiConfigurationName: String
|
||||
get() = disambiguateName("api")
|
||||
|
||||
override val implementationConfigurationName: String
|
||||
get() = disambiguateName("implementation")
|
||||
|
||||
override val compileOnlyConfigurationName: String
|
||||
get() = disambiguateName("compileOnly")
|
||||
|
||||
override val runtimeOnlyConfigurationName: String
|
||||
get() = disambiguateName("runtimeOnly")
|
||||
|
||||
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||
|
||||
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||
|
||||
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinCompilationToRunnableFiles(
|
||||
target: KotlinTarget,
|
||||
name: String
|
||||
) : AbstractKotlinCompilation(target, name), KotlinCompilationToRunnableFiles {
|
||||
override val runtimeDependencyConfigurationName: String
|
||||
get() = lowerCamelCaseName(
|
||||
target.disambiguationClassifier,
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||
"runtimeClasspath"
|
||||
)
|
||||
|
||||
override lateinit var runtimeDependencyFiles: FileCollection
|
||||
}
|
||||
|
||||
internal fun KotlinCompilation.disambiguateName(simpleName: String): String {
|
||||
return lowerCamelCaseName(
|
||||
target.disambiguationClassifier,
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||
simpleName
|
||||
)
|
||||
}
|
||||
|
||||
open class KotlinJvmCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilationToRunnableFiles(target, name), KotlinCompilationWithResources {
|
||||
override val processResourcesTaskName: String
|
||||
get() = disambiguateName("processResources")
|
||||
}
|
||||
|
||||
class KotlinWithJavaCompilation(
|
||||
target: KotlinWithJavaTarget,
|
||||
name: String
|
||||
) : AbstractKotlinCompilationToRunnableFiles(target, name), KotlinCompilationWithResources {
|
||||
lateinit var javaSourceSet: SourceSet
|
||||
|
||||
override val output: SourceSetOutput
|
||||
get() = javaSourceSet.output
|
||||
|
||||
override val processResourcesTaskName: String
|
||||
get() = javaSourceSet.processResourcesTaskName
|
||||
|
||||
override var runtimeDependencyFiles: FileCollection
|
||||
get() = javaSourceSet.runtimeClasspath
|
||||
set(value) { javaSourceSet.runtimeClasspath = value }
|
||||
|
||||
override val runtimeDependencyConfigurationName: String
|
||||
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||
|
||||
override val compileDependencyConfigurationName: String
|
||||
get() = javaSourceSet.compileClasspathConfigurationName
|
||||
|
||||
override val runtimeOnlyConfigurationName: String
|
||||
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||
|
||||
override val implementationConfigurationName: String
|
||||
get() = javaSourceSet.implementationConfigurationName
|
||||
|
||||
override val apiConfigurationName: String
|
||||
get() = javaSourceSet.apiConfigurationName
|
||||
|
||||
override val compileOnlyConfigurationName: String
|
||||
get() = javaSourceSet.compileOnlyConfigurationName
|
||||
|
||||
override val compileAllTaskName: String
|
||||
get() = javaSourceSet.classesTaskName
|
||||
|
||||
override var compileDependencyFiles: FileCollection
|
||||
get() = javaSourceSet.compileClasspath
|
||||
set(value) { javaSourceSet.compileClasspath = value }
|
||||
|
||||
fun source(javaSourceSet: SourceSet) {
|
||||
with(target.project) {
|
||||
afterEvaluate {
|
||||
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmAndroidCompilation(
|
||||
target: KotlinAndroidTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
): AbstractKotlinCompilationToRunnableFiles(target, name)
|
||||
|
||||
class KotlinJsCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilation(target, name)
|
||||
|
||||
class KotlinCommonCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilation(target, name)
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
|
||||
abstract class AbstractKotlinTarget (
|
||||
override val project: Project
|
||||
) : KotlinTarget {
|
||||
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||
|
||||
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||
|
||||
override val defaultConfigurationName: String
|
||||
get() = disambiguateName("default")
|
||||
|
||||
override val apiElementsConfigurationName: String
|
||||
get() = disambiguateName("apiElements")
|
||||
|
||||
override val runtimeElementsConfigurationName: String
|
||||
get() = disambiguateName("runtimeElements")
|
||||
|
||||
override val artifactsTaskName: String
|
||||
get() = disambiguateName("jar")
|
||||
|
||||
override fun toString(): String = "target $name ($platformType)"
|
||||
|
||||
override fun createUsageContexts(): Set<UsageContext> = setOf(
|
||||
KotlinPlatformUsageContext(project, this, KotlinSoftwareComponent.kotlinApiUsage(project), apiElementsConfigurationName),
|
||||
KotlinPlatformUsageContext(project, this, KotlinSoftwareComponent.kotlinRuntimeUsage(project), runtimeElementsConfigurationName)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
||||
lowerCamelCaseName(targetName, simpleName)
|
||||
|
||||
open class KotlinAndroidTarget(
|
||||
override val targetName: String,
|
||||
project: Project
|
||||
) : AbstractKotlinTarget(project) {
|
||||
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.jvm
|
||||
|
||||
private val compilationFactory = KotlinJvmAndroidCompilationFactory(project, this)
|
||||
|
||||
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
|
||||
project.container(compilationFactory.itemClass, compilationFactory)
|
||||
|
||||
override fun createUsageContexts(): Set<UsageContext> {
|
||||
//TODO setup Android libraries publishing. This will likely require new API in the Android Gradle plugin
|
||||
return emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
open class KotlinWithJavaTarget(
|
||||
project: Project,
|
||||
override val platformType: KotlinPlatformType,
|
||||
override val targetName: String
|
||||
) : AbstractKotlinTarget(project) {
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
|
||||
override val defaultConfigurationName: String
|
||||
get() = Dependency.DEFAULT_CONFIGURATION
|
||||
|
||||
override val apiElementsConfigurationName: String
|
||||
get() = JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME
|
||||
|
||||
override val runtimeElementsConfigurationName: String
|
||||
get() = JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
|
||||
|
||||
override val artifactsTaskName: String
|
||||
get() = JavaPlugin.JAR_TASK_NAME
|
||||
|
||||
override val compilations: NamedDomainObjectContainer<KotlinWithJavaCompilation> =
|
||||
project.container(KotlinWithJavaCompilation::class.java,
|
||||
KotlinWithJavaCompilationFactory(project, this)
|
||||
)
|
||||
}
|
||||
|
||||
open class KotlinOnlyTarget<T : KotlinCompilation>(
|
||||
project: Project,
|
||||
override val platformType: KotlinPlatformType
|
||||
) : AbstractKotlinTarget(project) {
|
||||
|
||||
override lateinit var compilations: NamedDomainObjectContainer<T>
|
||||
internal set
|
||||
|
||||
override lateinit var targetName: String
|
||||
internal set
|
||||
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
}
|
||||
+3
-7
@@ -7,12 +7,8 @@ package org.jetbrains.kotlin.gradle.scripting.internal
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension
|
||||
|
||||
class ScriptingGradleSubplugin : Plugin<Project> {
|
||||
@@ -39,10 +35,10 @@ class ScriptingKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!ScriptingGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.utils
|
||||
|
||||
import org.gradle.api.Project
|
||||
|
||||
fun Project.addExtendsFromRelation(extendingConfigurationName: String, extendsFromConfigurationName: String) {
|
||||
if (extendingConfigurationName != extendsFromConfigurationName) {
|
||||
project.dependencies.add(extendingConfigurationName, project.configurations.getByName(extendsFromConfigurationName))
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.utils
|
||||
|
||||
internal fun lowerCamelCaseName(vararg nameParts: String?): String {
|
||||
val nonEmptyParts = nameParts.mapNotNull { it?.takeIf(String::isNotEmpty) }
|
||||
return nonEmptyParts.drop(1).joinToString(
|
||||
separator = "",
|
||||
prefix = nonEmptyParts.firstOrNull().orEmpty(),
|
||||
transform = String::capitalize
|
||||
)
|
||||
}
|
||||
+7
-14
@@ -18,16 +18,9 @@ package org.jetbrains.kotlin.noarg.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.noarg.gradle.model.builder.NoArgModelBuilder
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -58,12 +51,12 @@ class NoArgKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = NoArgGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!NoArgGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
+7
-14
@@ -18,16 +18,9 @@ package org.jetbrains.kotlin.samWithReceiver.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.noarg.gradle.model.builder.SamWithReceiverModelBuilder
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -53,12 +46,12 @@ class SamWithReceiverKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompi
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = SamWithReceiverGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!SamWithReceiverGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user