com.grab.grazel.gradle.variant.AndroidVariants.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grazel-gradle-plugin Show documentation
Show all versions of grazel-gradle-plugin Show documentation
A Gradle plugin to automate Bazel migration for Android projects
The newest version!
package com.grab.grazel.gradle.variant
import com.android.build.gradle.api.BaseVariant
import com.android.builder.model.BaseConfig
import com.android.builder.model.BuildType
import com.android.builder.model.ProductFlavor
import com.google.common.base.MoreObjects
import com.grab.grazel.gradle.variant.Classpath.Compile
import com.grab.grazel.gradle.variant.Classpath.Runtime
import com.grab.grazel.gradle.variant.VariantType.AndroidBuild
import com.grab.grazel.gradle.variant.VariantType.AndroidTest
import com.grab.grazel.gradle.variant.VariantType.JvmBuild
import com.grab.grazel.gradle.variant.VariantType.Lint
import com.grab.grazel.gradle.variant.VariantType.Test
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
/**
* [Variant] implementation used to represent a Variant created by Android Gradle plugin which is
* usually a mix of flavor + build type.
*/
class AndroidVariant(
override val project: Project,
override val backingVariant: BaseVariant,
) : ConfigurationParsingVariant {
override val name: String = backingVariant.name
override val variantType: VariantType = backingVariant.toVariantType()
/**
* Calculate the base name from variant. Useful for parsing since configuration
* names are typically in camel case.
*
* Eg:
* androidTestPaidDebug -> PaidDebug
*/
override val baseName = backingVariant.baseName
.split('-')
.dropLast(1)
.joinToString(separator = "", transform = String::capitalize)
override val extendsFrom: Set by lazy {
buildList {
add(DEFAULT_VARIANT)
addAll(backingVariant.productFlavors.map { it.name })
add(backingVariant.buildType.name)
if (variantType.isTest) {
add(TEST_VARIANT)
add(baseVariantName)
if (variantType.isAndroidTest) {
add(ANDROID_TEST_VARIANT)
}
add(backingVariant.buildType.name + variantType.testSuffix)
}
}.filter { it != name && it.trim().isNotEmpty() }.toSet()
}
override val compileConfiguration get() = setOf(backingVariant.compileConfiguration)
override val runtimeConfiguration get() = setOf(backingVariant.runtimeConfiguration)
override val annotationProcessorConfiguration
get() = parseAnnotationProcessorConfigurations(
fallback = backingVariant.annotationProcessorConfiguration
)
override fun toString() = MoreObjects.toStringHelper(this)
.add("project", project.path)
.add("name", name)
.add("variantType", variantType)
.toString()
private val baseVariantName: String
get() = (backingVariant.flavorName + backingVariant.buildType.name.capitalize()).replaceFirstChar {
if (it.isUpperCase()) it.toLowerCase().toString() else it.toString()
}
}
/**
* Type to represent a non Android's [BaseVariant] type. Both flavors and buildTypes are permuted
* to create variants, but we also need non-variant type that represents each [BuildType] and
* [ProductFlavor] but not the variants created by them, this type represents that.
*
* For parsing, [toIgnoreKeywords] is used to filter out any configuration that appears to configuration
* from a variant. For [BuildType] it will be all productFlavors and vice versa.
*/
abstract class AndroidNonVariant(
override val project: Project,
override val backingVariant: T,
override val variantType: VariantType,
private val toIgnoreKeywords: Set
) : ConfigurationParsingVariant where T : BaseConfig {
override val name
get() = backingVariant.name + when (variantType) {
AndroidTest, Test -> variantType.testSuffix
Lint -> Lint.name
else -> ""
}
override val baseName get() = backingVariant.name.capitalize()
override val extendsFrom: Set by lazy {
buildList {
add(DEFAULT_VARIANT)
if (variantType.isTest) {
add(backingVariant.name)
add(TEST_VARIANT)
if (variantType.isAndroidTest) {
add(ANDROID_TEST_VARIANT)
}
}
}.toSet()
}
override val variantConfigurations: Set
get() = super.variantConfigurations
.asSequence()
.filter { config -> toIgnoreKeywords.none { config.name.contains(it, true) } }
.toSet()
override val compileConfiguration by lazy { classpathConfiguration(classpath = Compile) }
override val runtimeConfiguration by lazy { classpathConfiguration(classpath = Runtime) }
override val annotationProcessorConfiguration: Set
get() {
val apConfig = "%sAnnotationProcessor"
val buildTypeConfigs = parseAnnotationProcessorConfigurations(
fallback = project.configurations[apConfig.format(baseName.toLowerCase())]!!,
)
val flavorConfig = toIgnoreKeywords.flatMap { flavor ->
val namePattern = flavor + baseName
project.configurations[apConfig.format(namePattern)]?.let { fallback ->
parseAnnotationProcessorConfigurations(
fallback = fallback,
namePattern = namePattern,
basePattern = namePattern
)
} ?: emptySet()
}
return (buildTypeConfigs + flavorConfig).toSet()
}
override val kotlinCompilerPluginConfiguration get() = emptySet()
override fun toString() = MoreObjects.toStringHelper(this)
.add("project", project.path)
.add("name", name)
.add("variantType", variantType)
.toString()
}
/**
* A [Variant] implementation to denote a [BuildType] with [toIgnoreKeywords] set to product flavors
*
* @param project The project this build type belongs to
* @param backingVariant The [BuildType] of this variant
* @param variantType [BuildType] typically is not associated with certain source set alone however
* this is used to hint the type of source set for parsing.
* @param flavors The set of [ProductFlavor] names contained in the project, used for parsing to filter
* out any permutation of buildType + flavors
*/
class AndroidBuildType(
override val project: Project,
override val backingVariant: BuildType,
override val variantType: VariantType,
private val flavors: Set
) : AndroidNonVariant(
project = project,
backingVariant = backingVariant,
variantType = variantType,
toIgnoreKeywords = flavors
)
/**
* A [Variant] implementation to denote a [ProductFlavor] with [toIgnoreKeywords] set to buildTypes
*
* @param project The project this flavor belongs to
* @param backingVariant The [ProductFlavor] of this variant
* @param variantType [ProductFlavor] typically is not associated with certain source set type alone however
* this is used to hint the type of source set for parsing.
* @param buildTypes The set of [BuildType] names contained in the project, used for parsing to filter
* out any permutation of buildType + flavors
*/
class AndroidFlavor(
override val project: Project,
override val backingVariant: ProductFlavor,
override val variantType: VariantType,
private val buildTypes: Set
) : AndroidNonVariant(
project = project,
backingVariant = backingVariant,
variantType = variantType,
toIgnoreKeywords = buildTypes
)
data class DefaultVariantData(
val project: Project,
val variantType: VariantType,
val ignoreKeywords: Set,
val name: String = when (variantType) {
AndroidBuild -> DEFAULT_VARIANT
AndroidTest -> ANDROID_TEST_VARIANT
Lint -> LINT_VARIANT
else -> TEST_VARIANT
},
)
fun AndroidDefaultVariant(
project: Project,
variantType: VariantType,
ignoreKeywords: Set,
) = AndroidDefaultVariant(DefaultVariantData(project, variantType, ignoreKeywords))
/**
* A [Variant] implementation to denote the default type i.e. without any build type or variant
* specific data.
*/
class AndroidDefaultVariant(
private val defaultVariantData: DefaultVariantData
) : ConfigurationParsingVariant {
override val name: String get() = defaultVariantData.name
override val baseName: String get() = ""
override val backingVariant: DefaultVariantData get() = defaultVariantData
override val project: Project get() = defaultVariantData.project
override val variantType: VariantType get() = defaultVariantData.variantType
override val extendsFrom: Set = buildSet {
if (variantType.isTest) add(DEFAULT_VARIANT)
if (variantType.isAndroidTest) add(TEST_VARIANT)
}
private val ignoreKeywords get() = defaultVariantData.ignoreKeywords
override val variantConfigurations: Set
get() = project.configurations
.asSequence()
.filter { config ->
val name = config.name
ignoreKeywords.none { ignore -> name.contains(ignore, true) }
}.filter {
val configName = it.name
when (variantType) {
AndroidBuild -> !configName.isTest()
AndroidTest -> configName.isAndroidTest()
Test -> configName.isUnitTest()
Lint -> configName.isLint()
JvmBuild -> error("Invalid variant type ${JvmBuild.name} for Android variant")
}
}.toSet()
override val compileConfiguration: Set by lazy {
classpathConfiguration(Compile, namePattern = "", basePattern = "")
}
override val runtimeConfiguration: Set by lazy {
classpathConfiguration(Runtime, namePattern = "", basePattern = "")
}
override val annotationProcessorConfiguration: Set
get() = parseAnnotationProcessorConfigurations(
fallback = project.configurations["annotationProcessor"]!!,
"",
""
)
override val kotlinCompilerPluginConfiguration: Set
get() = buildList {
project.configurations["kotlinCompilerPluginClasspath"]?.let(::add)
project.configurations["kotlin-extension"]?.let(::add)
}.toSet()
override fun toString(): String = MoreObjects.toStringHelper(this)
.add("project", project.path)
.add("name", name)
.add("variantType", variantType)
.toString()
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy