Partial cleanup & refactoring of the Android plugin

The `KotlinAndroidPlugin` used to support two different sets of APIs of
the Android Gradle plugin and used `AbstractAndroidProjectHandler` to
wrap those APIs. Now that there's only one implementation, it
doesn't need the generic `V` (variant data), and some cleanup is needed.
This commit is contained in:
Sergey Igushkin
2019-08-23 16:02:33 +03:00
parent 0e59553d12
commit bb6f406be4
5 changed files with 42 additions and 48 deletions
@@ -654,7 +654,7 @@ internal open class KotlinAndroidPlugin(
fun androidTargetHandler( fun androidTargetHandler(
kotlinPluginVersion: String, kotlinPluginVersion: String,
androidTarget: KotlinAndroidTarget androidTarget: KotlinAndroidTarget
): AbstractAndroidProjectHandler<*> { ): AbstractAndroidProjectHandler {
val tasksProvider = AndroidTasksProvider(androidTarget.targetName) val tasksProvider = AndroidTasksProvider(androidTarget.targetName)
val version = loadAndroidPluginVersion() val version = loadAndroidPluginVersion()
@@ -687,37 +687,35 @@ class KotlinConfigurationTools internal constructor(
val kotlinPluginVersion: String val kotlinPluginVersion: String
) )
abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationTools: KotlinConfigurationTools) { abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) {
protected val logger = Logging.getLogger(this.javaClass) protected val logger = Logging.getLogger(this.javaClass)
abstract fun forEachVariant(project: Project, action: (V) -> Unit): Unit abstract fun forEachVariant(project: Project, action: (BaseVariant) -> Unit): Unit
abstract fun getTestedVariantData(variantData: V): V? abstract fun getResDirectories(variantData: BaseVariant): FileCollection
abstract fun getResDirectories(variantData: V): FileCollection abstract fun getFlavorNames(variant: BaseVariant): List<String>
abstract fun getVariantName(variant: V): String abstract fun getBuildTypeName(variant: BaseVariant): String
abstract fun getFlavorNames(variant: V): List<String> abstract fun getLibraryOutputTask(variant: BaseVariant): Any?
abstract fun getBuildTypeName(variant: V): String
abstract fun getLibraryOutputTask(variant: V): Any?
protected abstract fun getSourceProviders(variantData: V): Iterable<SourceProvider> protected abstract fun getSourceProviders(variantData: BaseVariant): Iterable<SourceProvider>
protected abstract fun getAllJavaSources(variantData: V): Iterable<File> protected abstract fun getAllJavaSources(variantData: BaseVariant): Iterable<File>
protected abstract fun getJavaTask(variantData: V): AbstractCompile? protected abstract fun getJavaTask(variantData: BaseVariant): AbstractCompile?
protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: V, javaSourceDirectory: File): Unit protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariant, javaSourceDirectory: File): Unit
protected open fun checkVariantIsValid(variant: V) = Unit protected open fun checkVariantIsValid(variant: BaseVariant) = Unit
protected open fun setUpDependencyResolution(variant: V, compilation: KotlinJvmAndroidCompilation) = Unit protected open fun setUpDependencyResolution(variant: BaseVariant, compilation: KotlinJvmAndroidCompilation) = Unit
protected abstract fun wireKotlinTasks( protected abstract fun wireKotlinTasks(
project: Project, project: Project,
compilation: KotlinJvmAndroidCompilation, compilation: KotlinJvmAndroidCompilation,
androidPlugin: BasePlugin, androidPlugin: BasePlugin,
androidExt: BaseExtension, androidExt: BaseExtension,
variantData: V, variantData: BaseVariant,
javaTask: AbstractCompile, javaTask: AbstractCompile,
kotlinTask: KotlinCompile kotlinTask: KotlinCompile
) )
protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData<V> protected abstract fun wrapVariantDataForKapt(variantData: BaseVariant): KaptVariantData<BaseVariant>
fun configureTarget(kotlinAndroidTarget: KotlinAndroidTarget) { fun configureTarget(kotlinAndroidTarget: KotlinAndroidTarget) {
val project = kotlinAndroidTarget.project val project = kotlinAndroidTarget.project
@@ -773,11 +771,11 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
// in afterEvaluate, a user's build script might have already attached item handlers to the compilations container, and those // in afterEvaluate, a user's build script might have already attached item handlers to the compilations container, and those
// handlers might break when fired on a compilation that is not yet properly configured (e.g. KT-29964): // handlers might break when fired on a compilation that is not yet properly configured (e.g. KT-29964):
kotlinAndroidTarget.compilationFactory.create(variantName).let { compilation -> kotlinAndroidTarget.compilationFactory.create(variantName).let { compilation ->
compilation.androidVariant = variant as BaseVariant compilation.androidVariant = variant
setUpDependencyResolution(variant, compilation) setUpDependencyResolution(variant, compilation)
preprocessVariant(variant, compilation, project, ext, plugin, kotlinOptions, kotlinConfigurationTools.kotlinTasksProvider) preprocessVariant(variant, compilation, project, kotlinOptions, kotlinConfigurationTools.kotlinTasksProvider)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(kotlinAndroidTarget.compilations as NamedDomainObjectCollection<in KotlinJvmAndroidCompilation>).add(compilation) (kotlinAndroidTarget.compilations as NamedDomainObjectCollection<in KotlinJvmAndroidCompilation>).add(compilation)
@@ -852,7 +850,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
// extendsFrom relationship. // extendsFrom relationship.
if (kotlinAndroidTarget.disambiguationClassifier != null) { if (kotlinAndroidTarget.disambiguationClassifier != null) {
val sourceSetToVariants = mutableMapOf<AndroidSourceSet, MutableList<V>>().apply { val sourceSetToVariants = mutableMapOf<AndroidSourceSet, MutableList<BaseVariant>>().apply {
forEachVariant(project) { variant -> forEachVariant(project) { variant ->
for (sourceSet in getSourceProviders(variant)) { for (sourceSet in getSourceProviders(variant)) {
val androidSourceSet = sourceSet as? AndroidSourceSet ?: continue val androidSourceSet = sourceSet as? AndroidSourceSet ?: continue
@@ -885,11 +883,9 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
} }
private fun preprocessVariant( private fun preprocessVariant(
variantData: V, variantData: BaseVariant,
compilation: KotlinJvmAndroidCompilation, compilation: KotlinJvmAndroidCompilation,
project: Project, project: Project,
androidExt: BaseExtension,
androidPlugin: BasePlugin,
rootKotlinOptions: KotlinJvmOptionsImpl, rootKotlinOptions: KotlinJvmOptionsImpl,
tasksProvider: KotlinTasksProvider tasksProvider: KotlinTasksProvider
) { ) {
@@ -935,7 +931,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
} }
private fun postprocessVariant( private fun postprocessVariant(
variantData: V, variantData: BaseVariant,
compilation: KotlinJvmAndroidCompilation, compilation: KotlinJvmAndroidCompilation,
project: Project, project: Project,
androidExt: BaseExtension, androidExt: BaseExtension,
@@ -951,7 +947,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
private fun applySubplugins( private fun applySubplugins(
project: Project, project: Project,
compilation: KotlinCompilation<*>, compilation: KotlinCompilation<*>,
variantData: V, variantData: BaseVariant,
subpluginEnvironment: SubpluginEnvironment subpluginEnvironment: SubpluginEnvironment
) { ) {
val kotlinTask = project.tasks.getByName(compilation.compileKotlinTaskName) as KotlinCompile val kotlinTask = project.tasks.getByName(compilation.compileKotlinTaskName) as KotlinCompile
@@ -965,7 +961,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
.forEach { configureSources(it, variantData, null) } .forEach { configureSources(it, variantData, null) }
} }
private fun configureSources(compileTask: AbstractCompile, variantData: V, compilation: KotlinCompilation<*>?) { private fun configureSources(compileTask: AbstractCompile, variantData: BaseVariant, compilation: KotlinCompilation<*>?) {
val logger = compileTask.project.logger val logger = compileTask.project.logger
for (provider in getSourceProviders(variantData)) { for (provider in getSourceProviders(variantData)) {
@@ -46,7 +46,7 @@ class SubpluginEnvironment(
kotlinTask: AbstractKotlinCompile<C>, kotlinTask: AbstractKotlinCompile<C>,
javaTask: AbstractCompile? = null, javaTask: AbstractCompile? = null,
variantData: Any? = null, variantData: Any? = null,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>? = null, androidProjectHandler: AbstractAndroidProjectHandler? = null,
kotlinCompilation: KotlinCompilation<*>? = null kotlinCompilation: KotlinCompilation<*>? = null
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> = addSubpluginOptions( ): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> = addSubpluginOptions(
project, project,
@@ -64,7 +64,7 @@ class SubpluginEnvironment(
pluginOptions: CompilerPluginOptions, pluginOptions: CompilerPluginOptions,
javaTask: AbstractCompile? = null, javaTask: AbstractCompile? = null,
variantData: Any? = null, variantData: Any? = null,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>? = null, androidProjectHandler: AbstractAndroidProjectHandler? = null,
kotlinCompilation: KotlinCompilation<*>? = null kotlinCompilation: KotlinCompilation<*>? = null
): List<KotlinGradleSubplugin<AbstractCompile>> { ): List<KotlinGradleSubplugin<AbstractCompile>> {
val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) } val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) }
@@ -22,13 +22,12 @@ import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import java.io.File import java.io.File
import java.util.concurrent.Callable import java.util.concurrent.Callable
class Android25ProjectHandler( class Android25ProjectHandler(
kotlinConfigurationTools: KotlinConfigurationTools kotlinConfigurationTools: KotlinConfigurationTools
) : AbstractAndroidProjectHandler<BaseVariant>(kotlinConfigurationTools) { ) : AbstractAndroidProjectHandler(kotlinConfigurationTools) {
override fun forEachVariant(project: Project, action: (BaseVariant) -> Unit) { override fun forEachVariant(project: Project, action: (BaseVariant) -> Unit) {
val androidExtension = project.extensions.getByName("android") val androidExtension = project.extensions.getByName("android")
@@ -96,18 +95,10 @@ class Android25ProjectHandler(
override fun getAllJavaSources(variantData: BaseVariant): Iterable<File> = override fun getAllJavaSources(variantData: BaseVariant): Iterable<File> =
variantData.getSourceFolders(SourceKind.JAVA).map { it.dir } variantData.getSourceFolders(SourceKind.JAVA).map { it.dir }
override fun getVariantName(variant: BaseVariant): String = variant.name
override fun getFlavorNames(variant: BaseVariant): List<String> = variant.productFlavors.map { it.name } override fun getFlavorNames(variant: BaseVariant): List<String> = variant.productFlavors.map { it.name }
override fun getBuildTypeName(variant: BaseVariant): String = variant.buildType.name override fun getBuildTypeName(variant: BaseVariant): String = variant.buildType.name
override fun getTestedVariantData(variantData: BaseVariant): BaseVariant? = when (variantData) {
is TestVariant -> variantData.testedVariant
is UnitTestVariant -> variantData.testedVariant as? BaseVariant
else -> null
}
override fun getJavaTask(variantData: BaseVariant): AbstractCompile? { override fun getJavaTask(variantData: BaseVariant): AbstractCompile? {
@Suppress("DEPRECATION") // There is always a Java compile task -- the deprecation was for Jack @Suppress("DEPRECATION") // There is always a Java compile task -- the deprecation was for Jack
return variantData::class.java.methods.firstOrNull { it.name == "getJavaCompileProvider" } return variantData::class.java.methods.firstOrNull { it.name == "getJavaCompileProvider" }
@@ -246,3 +237,11 @@ class Android25ProjectHandler(
override fun wrapVariantDataForKapt(variantData: BaseVariant): KaptVariantData<BaseVariant> = override fun wrapVariantDataForKapt(variantData: BaseVariant): KaptVariantData<BaseVariant> =
KaptVariant(variantData) KaptVariant(variantData)
} }
internal fun getTestedVariantData(variantData: BaseVariant): BaseVariant? = when (variantData) {
is TestVariant -> variantData.testedVariant
is UnitTestVariant -> variantData.testedVariant as? BaseVariant
else -> null
}
internal fun getVariantName(variant: BaseVariant): String = variant.name
@@ -6,6 +6,7 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility @file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin.mpp package org.jetbrains.kotlin.gradle.plugin.mpp
import com.android.build.gradle.api.BaseVariant
import org.gradle.api.InvalidUserDataException import org.gradle.api.InvalidUserDataException
import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project import org.gradle.api.Project
@@ -61,8 +62,7 @@ open class KotlinAndroidTarget(
var publishLibraryVariantsGroupedByFlavor = false var publishLibraryVariantsGroupedByFlavor = false
private fun checkPublishLibraryVariantsExist() { private fun checkPublishLibraryVariantsExist() {
// Capture type parameter T fun AbstractAndroidProjectHandler.getLibraryVariantNames() =
fun <T> AbstractAndroidProjectHandler<T>.getLibraryVariantNames() =
mutableSetOf<String>().apply { mutableSetOf<String>().apply {
forEachVariant(project) { forEachVariant(project) {
if (getLibraryOutputTask(it) != null) if (getLibraryOutputTask(it) != null)
@@ -92,9 +92,8 @@ open class KotlinAndroidTarget(
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents() KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents()
} }
// Capture the type parameter T for `AbstractAndroidProjectHandler` private fun AbstractAndroidProjectHandler.doCreateComponents(): Set<KotlinTargetComponent> {
private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> { val publishableVariants = mutableListOf<BaseVariant>()
val publishableVariants = mutableListOf<T>()
.apply { forEachVariant(project) { add(it) } } .apply { forEachVariant(project) { add(it) } }
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { } .toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
.filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true } .filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true }
@@ -161,8 +160,8 @@ open class KotlinAndroidTarget(
}.toSet() }.toSet()
} }
private fun <T> AbstractAndroidProjectHandler<T>.createAndroidUsageContexts( private fun AbstractAndroidProjectHandler.createAndroidUsageContexts(
variant: T, variant: BaseVariant,
compilation: KotlinCompilation<*>, compilation: KotlinCompilation<*>,
artifactClassifier: String? artifactClassifier: String?
): Set<DefaultKotlinUsageContext> { ): Set<DefaultKotlinUsageContext> {
@@ -164,7 +164,7 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
androidProjectHandler: Any? androidProjectHandler: Any?
): List<SubpluginOption> { ): List<SubpluginOption> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
androidProjectHandler as? AbstractAndroidProjectHandler<Any?> ?: return emptyList() androidProjectHandler as? AbstractAndroidProjectHandler ?: return emptyList()
val pluginOptions = arrayListOf<SubpluginOption>() val pluginOptions = arrayListOf<SubpluginOption>()
pluginOptions += SubpluginOption("features", pluginOptions += SubpluginOption("features",
@@ -209,7 +209,7 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val resDirectoriesForAllVariants = mutableListOf<FileCollection>() val resDirectoriesForAllVariants = mutableListOf<FileCollection>()
androidProjectHandler.forEachVariant(project) { variant -> androidProjectHandler.forEachVariant(project) { variant ->
if (androidProjectHandler.getTestedVariantData(variant) != null) return@forEachVariant if (getTestedVariantData(variant) != null) return@forEachVariant
resDirectoriesForAllVariants += androidProjectHandler.getResDirectories(variant) resDirectoriesForAllVariants += androidProjectHandler.getResDirectories(variant)
} }