Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Part 2: Initial work on Variant API #57

Merged
merged 4 commits into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ open class AssignStatement(
private val key: Assignable,
private val value: Assignee,
private val assignmentOp: AssignmentOp = EQUAL
) : Statement {
) : Assignee {
override fun write(level: Int, writer: PrintWriter) {
indent(level, writer)
if (!key.isEmpty()) {
Expand Down Expand Up @@ -131,7 +131,7 @@ interface AssignmentBuilder {
* A common pattern is to not add statements if a list is empty. This function only executes `block` if the given list
* is not empty.
*/
fun List<*>.notEmpty(block: () -> Unit) {
fun Collection<*>.notEmpty(block: () -> Unit) {
if (isNotEmpty()) block()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ package com.grab.grazel.di

import com.grab.grazel.GrazelExtension
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.AndroidVariantDataSource
import com.grab.grazel.gradle.AndroidVariantsExtractor
import com.grab.grazel.gradle.ConfigurationDataSource
import com.grab.grazel.gradle.DefaultAndroidVariantDataSource
import com.grab.grazel.gradle.DefaultAndroidVariantsExtractor
import com.grab.grazel.gradle.DefaultConfigurationDataSource
import com.grab.grazel.gradle.DefaultGradleProjectInfo
import com.grab.grazel.gradle.DefaultRepositoryDataSource
Expand All @@ -35,6 +31,12 @@ import com.grab.grazel.gradle.dependencies.DependenciesGraphsBuilder
import com.grab.grazel.gradle.dependencies.DependenciesModule
import com.grab.grazel.gradle.dependencies.DependencyGraphs
import com.grab.grazel.gradle.dependencies.MavenInstallArtifactsCalculator
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import com.grab.grazel.gradle.variant.AndroidVariantsExtractor
import com.grab.grazel.gradle.variant.DefaultAndroidVariantDataSource
import com.grab.grazel.gradle.variant.DefaultAndroidVariantsExtractor
import com.grab.grazel.gradle.variant.VariantBuilder
import com.grab.grazel.gradle.variant.VariantModule
import com.grab.grazel.migrate.android.AndroidInstrumentationBinaryDataExtractor
import com.grab.grazel.migrate.builder.AndroidBinaryTargetBuilderModule
import com.grab.grazel.migrate.builder.AndroidInstrumentationBinaryTargetBuilderModule
Expand Down Expand Up @@ -86,12 +88,14 @@ internal interface GrazelComponent {
fun mavenInstallArtifactsCalculator(): Lazy<MavenInstallArtifactsCalculator>

fun androidInstrumentationBinaryDataExtractor(): Lazy<AndroidInstrumentationBinaryDataExtractor>
fun variantBuilder(): Lazy<VariantBuilder>
}

@Module(
includes = [
MigrationCriteriaModule::class,
DependenciesModule::class
DependenciesModule::class,
VariantModule::class
]
)
internal interface GrazelModule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,7 @@

package com.grab.grazel.gradle

import com.android.build.gradle.AppExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.api.UnitTestVariant
import com.android.builder.model.BuildType
import com.android.builder.model.ProductFlavor
import com.grab.grazel.extension.DefaultVariantFilter
import com.grab.grazel.extension.VariantFilter
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
import javax.inject.Inject
import javax.inject.Singleton


sealed class VariantInfo {
Expand All @@ -44,145 +31,4 @@ sealed class VariantInfo {
data class AndroidVariant(val baseVariant: BaseVariant) : VariantInfo() {
override fun toString(): String = baseVariant.name
}
}

internal interface AndroidVariantDataSource {
/**
* Variant filter instance to filter out unsupported variants
*/
val variantFilter: Action<VariantFilter>?

/**
* This method will return the flavors which are ignored after evaluate the ignore variants
* determined by [variantFilter]
*/
fun getIgnoredFlavors(project: Project): List<ProductFlavor>

/**
* This method will return the variants which are ignored by the configuration determined by [variantFilter]
*/
fun getIgnoredVariants(project: Project): List<BaseVariant>

/**
* @return The list of variants that can be migrated.
*/
fun getMigratableVariants(project: Project): List<BaseVariant>

/**
* return all variants minus the ones that declared in filtered variants
*/
fun getMigratableVariants(
project: Project,
configurationScope: ConfigurationScope?
): Set<BaseVariant>
}

internal class DefaultAndroidVariantDataSource(
private val androidVariantsExtractor: AndroidVariantsExtractor,
override val variantFilter: Action<VariantFilter>? = null,
) : AndroidVariantDataSource {

override fun getMigratableVariants(
project: Project,
configurationScope: ConfigurationScope?
): Set<BaseVariant> {
return when (configurationScope) {
ConfigurationScope.TEST -> {
androidVariantsExtractor.getUnitTestVariants(project)
}
ConfigurationScope.ANDROID_TEST -> {
androidVariantsExtractor.getTestVariants(project)
}
else -> {
androidVariantsExtractor.getVariants(project)
}
}.filterNot(::ignoredVariantFilter).toSet()
}

override fun getIgnoredFlavors(project: Project): List<ProductFlavor> {
val supportFlavors = getMigratableVariants(project).flatMap(BaseVariant::getProductFlavors)
return androidVariantsExtractor.getFlavors(project)
.filter { flavor -> !supportFlavors.any { it.name == flavor.name } }
}

private fun Project.androidVariants() =
androidVariantsExtractor.getVariants(this) +
androidVariantsExtractor.getUnitTestVariants(this)

override fun getIgnoredVariants(project: Project): List<BaseVariant> {
return project.androidVariants().filter(::ignoredVariantFilter)
}

override fun getMigratableVariants(project: Project): List<BaseVariant> {
return project.androidVariants().filterNot(::ignoredVariantFilter)
}

private fun ignoredVariantFilter(
variant: BaseVariant
): Boolean = DefaultVariantFilter(variant)
.apply { variantFilter?.execute(this) }
.ignored
}

internal interface AndroidVariantsExtractor {
fun getUnitTestVariants(project: Project): Set<BaseVariant>
fun getTestVariants(project: Project): Set<BaseVariant>
fun getVariants(project: Project): Set<BaseVariant>
fun getFlavors(project: Project): Set<ProductFlavor>
fun getBuildTypes(project: Project): Set<BuildType>
}


@Singleton
internal class DefaultAndroidVariantsExtractor @Inject constructor() : AndroidVariantsExtractor {

private val Project.isAndroidAppOrDynFeature get() = project.isAndroidApplication || project.isAndroidDynamicFeature

override fun getVariants(project: Project): Set<BaseVariant> {
return when {
project.isAndroidAppOrDynFeature -> project.the<AppExtension>().applicationVariants
project.isAndroidLibrary -> project.the<LibraryExtension>().libraryVariants
else -> emptySet()
}
}

override fun getTestVariants(project: Project): Set<BaseVariant> {
return when {
project.isAndroidAppOrDynFeature -> project.the<AppExtension>().testVariants
project.isAndroidLibrary -> project.the<LibraryExtension>().testVariants
else -> emptySet()
}
}

override fun getUnitTestVariants(project: Project): Set<UnitTestVariant> {
return when {
project.isAndroidAppOrDynFeature -> project.the<AppExtension>().unitTestVariants
project.isAndroidLibrary -> project.the<LibraryExtension>().unitTestVariants
else -> emptySet()
}
}

override fun getFlavors(project: Project): Set<ProductFlavor> {
return when {
project.isAndroidAppOrDynFeature -> project.the<AppExtension>().productFlavors
project.isAndroidLibrary -> project.the<LibraryExtension>().productFlavors
else -> emptySet()
}
}

override fun getBuildTypes(project: Project): Set<BuildType> {
return when {
project.isAndroidAppOrDynFeature -> project.the<AppExtension>().buildTypes
project.isAndroidLibrary -> project.the<LibraryExtension>().buildTypes
else -> emptySet()
}
}
}

internal fun AndroidVariantDataSource.getMigratableBuildVariants(project: Project): List<BaseVariant> =
getMigratableVariants(project)
.filter { it !is UnitTestVariant && it !is TestVariant }

internal fun AndroidVariantDataSource.getMigratableUnitTestVariants(project: Project): List<BaseVariant> =
getMigratableVariants(project)
.filterIsInstance<UnitTestVariant>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.grab.grazel.GrazelExtension
import com.grab.grazel.gradle.VariantInfo.AndroidFlavor
import com.grab.grazel.gradle.VariantInfo.AndroidVariant
import com.grab.grazel.gradle.dependencies.BuildGraphType
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.findKaptConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const val KOTLIN_PLUGIN = "kotlin"
const val KOTLIN_ANDROID_PLUGIN = "kotlin-android"
const val KOTLIN_ANDROID_EXTENSION = "kotlin-android-extensions"
const val KOTLIN_PARCELIZE = "kotlin-parcelize"
const val KOTLIN_KAPT = "kotlin-kapt"
const val ANDROID_APPLICATION_PLUGIN = "com.android.application"
const val ANDROID_LIBRARY_PLUGIN = "com.android.library"
const val ANDROID_DYNAMIC_FEATURE = "com.android.dynamic-feature"
Expand Down Expand Up @@ -59,6 +60,7 @@ val Project.hasKotlinAndroidExtensions
get() = plugins.hasPlugin(KOTLIN_ANDROID_EXTENSION)
|| plugins.hasPlugin(KOTLIN_PARCELIZE)
val Project.isKotlin get() = isKotlinJvm || isKotlinAndroid
val Project.hasKapt get() = plugins.hasPlugin(KOTLIN_KAPT)

val Project.hasTestInstrumentationRunner
get() = !extensions
Expand All @@ -71,6 +73,7 @@ const val JAVA_LIBRARY_PLUGIN = "java-library"
const val APPLICATION = "application"
val Project.isJava get() = plugins.hasPlugin(JAVA_PLUGIN) || plugins.hasPlugin(JAVA_LIBRARY_PLUGIN)

val Project.isJvm get() = isKotlinJvm || isJava

/**
* @return True if the given project is migrated to Bazel. Calculated by checking for presence of `BUILD.bazel` file for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import com.grab.grazel.GrazelExtension
import com.grab.grazel.bazel.rules.MavenInstallArtifact
import com.grab.grazel.bazel.rules.MavenInstallArtifact.Exclusion.SimpleExclusion
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.gradle.AndroidVariantsExtractor
import com.grab.grazel.gradle.ConfigurationDataSource
import com.grab.grazel.gradle.ConfigurationScope
import com.grab.grazel.gradle.RepositoryDataSource
import com.grab.grazel.gradle.configurationScopes
import com.grab.grazel.gradle.variant.AndroidVariantsExtractor
import com.grab.grazel.util.GradleProvider
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
Expand All @@ -41,7 +41,7 @@ import javax.inject.Singleton
/**
* Maven group names for artifacts that should be excluded from dependencies calculation everywhere.
*/
internal val DEP_GROUP_EMBEDDED_BY_RULES = listOf(
internal val IGNORED_ARTIFACT_GROUPS = listOf(
"com.android.tools.build",
"org.jetbrains.kotlin"
)
Expand Down Expand Up @@ -296,7 +296,7 @@ internal class DefaultDependenciesDataSource @Inject constructor(
override fun hasIgnoredArtifacts(project: Project): Boolean {
return project.firstLevelModuleDependencies()
.flatMap { (listOf(it) + it.children).asSequence() }
.filter { !DEP_GROUP_EMBEDDED_BY_RULES.contains(it.moduleGroup) }
.filter { !IGNORED_ARTIFACT_GROUPS.contains(it.moduleGroup) }
.any { MavenArtifact(it.moduleGroup, it.moduleName).isIgnored }
}

Expand All @@ -317,7 +317,7 @@ internal class DefaultDependenciesDataSource @Inject constructor(
}
}
.map { it.second }
.filter { it.group != null && !DEP_GROUP_EMBEDDED_BY_RULES.contains(it.group) }
.filter { it.group != null && !IGNORED_ARTIFACT_GROUPS.contains(it.group) }
.filter {
val artifact = MavenArtifact(it.group, it.name)
!artifact.isExcluded && !artifact.isIgnored
Expand Down Expand Up @@ -384,7 +384,7 @@ internal class DefaultDependenciesDataSource @Inject constructor(

/**
* Collects first level module dependencies from their resolved configuration. Additionally, excludes any artifacts
* that are not meant to be used in Bazel as defined by [DEP_GROUP_EMBEDDED_BY_RULES]
* that are not meant to be used in Bazel as defined by [IGNORED_ARTIFACT_GROUPS]
*
* @return Sequence of [DefaultResolvedDependency] in the first level
*/
Expand All @@ -401,7 +401,7 @@ internal class DefaultDependenciesDataSource @Inject constructor(
sequenceOf<ResolvedDependency>()
}
}.filterIsInstance<DefaultResolvedDependency>()
.filter { !DEP_GROUP_EMBEDDED_BY_RULES.contains(it.moduleGroup) }
.filter { !IGNORED_ARTIFACT_GROUPS.contains(it.moduleGroup) }
}

internal fun firstLevelModuleDependencies(project: Project) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import com.google.common.graph.MutableValueGraph
import com.google.common.graph.ValueGraphBuilder
import com.grab.grazel.di.qualifiers.RootProject
import com.grab.grazel.extension.TestExtension
import com.grab.grazel.gradle.AndroidVariantDataSource
import com.grab.grazel.gradle.ConfigurationDataSource
import com.grab.grazel.gradle.ConfigurationScope
import com.grab.grazel.gradle.isAndroid
import com.grab.grazel.gradle.isJava
import com.grab.grazel.gradle.isKotlinJvm
import com.grab.grazel.gradle.variant.AndroidVariantDataSource
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import javax.inject.Inject
Expand Down
Loading