Skip to content

Commit

Permalink
POC#1 (#122)
Browse files Browse the repository at this point in the history
Enhanced version of catalog API's

- Standardized names generator
- Strict versions enforced
- Bundle API automatically adds libs
- new deps api's for version catalog synthetic accessors
  • Loading branch information
stepango authored May 17, 2023
1 parent 61d1058 commit 2ed2426
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 57 deletions.
28 changes: 13 additions & 15 deletions application/common/extensions/android-util/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
androidUtil(
packageName = "com.stepango.blockme.common.extensions.android.util",
owner = Teams.core,
dependencies = deps(
androidx.constraintlayout,
androidx.core_ktx,
androidx.constraintlayout,
androidx.fragment,
androidx.viewmodel,
androidx.navigation,
androidx.recyclerview,
androidx.paging,
google.material,
io.coil
) + deps(
target(":common:placeholder:res")
)
)
dependencies =
deps(
androidx.constraintlayout,
androidx.core_ktx,
androidx.constraintlayout,
androidx.fragment,
androidx.viewmodel,
androidx.navigation,
androidx.recyclerview,
androidx.paging,
google.material,
) + deps(libs.bundles.coil) + deps(target(":common:placeholder:res"))
)
3 changes: 2 additions & 1 deletion application/core/mvvm/library/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ androidLibrary(
androidx.paging,
dataBinding.runtime,
google.dagger,
jakewharton.timber
)+ deps(
libs.jakewharton.timber,
),

testDependencies = deps(
Expand Down
3 changes: 2 additions & 1 deletion application/feature/characters/detail/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ impl(
androidx.paging,
google.material,
google.dagger,
jakewharton.timber,
kotlinx.coroutines_core,
viewbinding.viewpropertydelegate
) + deps(
libs.jakewharton.timber,
) + deps(
target(":feature:characters:core:api"),
target(":feature:characters:favorite:api"),
Expand Down
41 changes: 41 additions & 0 deletions application/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,47 @@ plugins {

rootProject.name = "application"

val filteredTokens = listOf("com", "io", "net", "org")
val coilVersion = "2.1.0"

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
addLibrary("com.jakewharton.timber:timber:4.7.1")
addBundle("coil", "io.coil-kt:coil:$coilVersion", "io.coil-kt:coil-base:$coilVersion")
}
}
}

fun VersionCatalogBuilder.addBundle(
name: String,
vararg groupArtifactVersion: String,
nameGenerator: (String) -> String = ::defaultNameGenerator
): String {
bundle(name, groupArtifactVersion.map { addLibrary(it, nameGenerator) })
return name
}

fun VersionCatalogBuilder.addLibrary(
groupArtifactVersion: String,
nameGenerator: (String) -> String = ::defaultNameGenerator
): String {
val (group, artifact, version) = groupArtifactVersion.split(":")
return nameGenerator(groupArtifactVersion).apply {
library(this, group, artifact).version { strictly(version) }
}
}

fun defaultNameGenerator(groupArtifactVersion: String) =
groupArtifactVersion
.split(":")
.dropLast(1)
.fold(emptyList<String>()) { acc, s -> acc + s.split(".", "-") }
.filter { it !in filteredTokens }
.distinct()
.joinToString(".")
.also { println("Generated name $it for $groupArtifactVersion") }

// refer to this issue https://github.com/gradle/gradle/issues/18536
// tools.forma.dependencies are applied in buildscript {} block
includeBuild("../build-dependencies")
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,5 @@ import org.gradle.kotlin.dsl.embeddedKotlinVersion
*/
class DepgenPlugin : Plugin<Settings> {
override fun apply(settings: Settings) {
settings.dependencyResolutionManagement {
versionCatalogs {
create("libs") {
// For test purposes only
library("kotlin-stdlib", "org.jetbrains.kotlin:kotlin-stdlib:$embeddedKotlinVersion")
}
}
}
}
}
92 changes: 61 additions & 31 deletions plugins/deps-core/src/main/java/dependencies.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import java.io.File
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExternalModuleDependencyBundle
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.provider.Provider
import tools.forma.deps.ConfigurationType
import tools.forma.deps.DepType
import tools.forma.deps.EmptyDependency
Expand All @@ -15,7 +20,6 @@ import tools.forma.deps.PlatformSpec
import tools.forma.deps.TargetDependency
import tools.forma.deps.TargetSpec
import tools.forma.target.FormaTarget
import java.io.File

val DepType.names: List<NameSpec>
get(): List<NameSpec> = filterIsInstance(NameSpec::class.java)
Expand All @@ -26,20 +30,34 @@ val DepType.targets: List<TargetSpec>
val DepType.files: List<FileSpec>
get(): List<FileSpec> = filterIsInstance(FileSpec::class.java)

infix operator fun FormaDependency.plus(dep: FormaDependency): MixedDependency = MixedDependency(
dependency.names + dep.dependency.names,
dependency.targets + dep.dependency.targets,
dependency.files + dep.dependency.files
)

inline fun <reified T : FormaDependency> emptyDependency(): T = when(T::class) {
FormaDependency::class -> EmptyDependency as T
NamedDependency::class -> NamedDependency() as T
FileDependency::class -> FileDependency() as T
TargetDependency::class -> TargetDependency() as T
MixedDependency::class -> MixedDependency() as T
else -> throw IllegalArgumentException("Illegal Empty dependency, expected ${T::class.simpleName}")
}
val <T : Dependency> Provider<T>.dep: NameSpec
get() = with(get()) { NameSpec("$group:$name:$version", Implementation) }

val Dependency.dep: NameSpec
get() = NameSpec("$group:$name:$version", Implementation)

val Provider<ExternalModuleDependencyBundle>.dep: List<NameSpec>
get() = get().map { it.dep }

infix operator fun FormaDependency.plus(dep: FormaDependency): MixedDependency =
MixedDependency(
dependency.names + dep.dependency.names,
dependency.targets + dep.dependency.targets,
dependency.files + dep.dependency.files
)

inline fun <reified T : FormaDependency> emptyDependency(): T =
when (T::class) {
FormaDependency::class -> EmptyDependency as T
NamedDependency::class -> NamedDependency() as T
FileDependency::class -> FileDependency() as T
TargetDependency::class -> TargetDependency() as T
MixedDependency::class -> MixedDependency() as T
else ->
throw IllegalArgumentException(
"Illegal Empty dependency, expected ${T::class.simpleName}"
)
}

fun FormaDependency.forEach(
nameAction: (NameSpec) -> Unit = {},
Expand All @@ -58,15 +76,14 @@ fun FormaDependency.forEach(
}

internal fun FormaDependency.hasConfigType(configType: ConfigurationType): Boolean {
dependency.forEach { dep ->
if (dep.config == configType) return true
}
dependency.forEach { dep -> if (dep.config == configType) return true }
return false
}

fun deps(vararg names: String): NamedDependency = transitiveDeps(names = *names, transitive = false)
fun deps(vararg names: String): NamedDependency = transitiveDeps(names = names, transitive = false)

fun platform(vararg names: String): PlatformDependency = transitivePlatform(*names, transitive = false)
fun platform(vararg names: String): PlatformDependency =
transitivePlatform(*names, transitive = false)

fun transitivePlatform(vararg names: String, transitive: Boolean = true): PlatformDependency =
PlatformDependency(names.toList().map { PlatformSpec(it, Implementation, transitive) })
Expand All @@ -76,32 +93,45 @@ fun transitiveDeps(vararg names: String, transitive: Boolean = true): NamedDepen

@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated(
"Deprecated in favor of targets version of this function:\n" +
"deps(target(\":name\"))"
"Deprecated in favor of targets version of this function:\n" + "deps(target(\":name\"))"
)
fun deps(vararg projects: Project): TargetDependency =
TargetDependency(projects.toList().map { TargetSpec(it.target, Implementation) })
TargetDependency(projects.map { TargetSpec(it.target, Implementation) })

fun deps(vararg targets: FormaTarget): TargetDependency =
TargetDependency(targets.toList().map { TargetSpec(it, Implementation) })
TargetDependency(targets.map { TargetSpec(it, Implementation) })

fun deps(vararg files: File): FileDependency =
FileDependency(files.toList().map { FileSpec(it, Implementation) })
FileDependency(files.map { FileSpec(it, Implementation) })

fun deps(vararg dependencies: NamedDependency): NamedDependency =
dependencies.flatMap { it.names }.let(::NamedDependency)

@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> deps(vararg dependencies: Provider<T>): NamedDependency =
when (T::class) {
Dependency::class,
MinimalExternalModuleDependency::class ->
dependencies.map { (it as Provider<MinimalExternalModuleDependency>).dep }
ExternalModuleDependencyBundle::class ->
dependencies.flatMap { (it as Provider<ExternalModuleDependencyBundle>).dep }
else -> throw IllegalArgumentException("Unsupported dependency type ${T::class.simpleName}")
}.let(::NamedDependency)

fun deps(vararg dependencies: TargetDependency): TargetDependency =
dependencies.flatMap { it.targets }.let(::TargetDependency)

fun kapt(vararg names: String): NamedDependency =
NamedDependency(names.toList().map { NameSpec(it, Kapt, true) })

val String.dep: NamedDependency get() = deps(this)
NamedDependency(names.map { NameSpec(it, Kapt, true) })

val String.kapt: NamedDependency get() = kapt(this)
val String.dep: NamedDependency
get() = deps(this)

val Project.target: FormaTarget get() = FormaTarget(this)
val String.kapt: NamedDependency
get() = kapt(this)

fun Project.target(name: String): FormaTarget = FormaTarget(project(":" + name.substring(1).replace(":", "-")))
val Project.target: FormaTarget
get() = FormaTarget(this)

fun Project.target(name: String): FormaTarget =
FormaTarget(project(":" + name.substring(1).replace(":", "-")))
2 changes: 1 addition & 1 deletion plugins/validation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ version = "0.0.1"

dependencies {
implementation(project(":target"))
}
}

0 comments on commit 2ed2426

Please sign in to comment.