Skip to content

Commit ad1d379

Browse files
authored
Merge pull request #851 from square/rick/gradle-property-conventions
binding extension properties to Gradle properties
2 parents ca8e11a + e40306c commit ad1d379

File tree

3 files changed

+246
-9
lines changed

3 files changed

+246
-9
lines changed

gradle-plugin/api/gradle-plugin.api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public final class com/squareup/anvil/plugin/AndroidVariantFilter : com/squareup
1616
}
1717

1818
public abstract class com/squareup/anvil/plugin/AnvilExtension {
19-
public fun <init> (Lorg/gradle/api/model/ObjectFactory;)V
19+
public fun <init> (Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;)V
2020
public final fun getAddOptionalAnnotations ()Lorg/gradle/api/provider/Property;
2121
public final fun getDisableComponentMerging ()Lorg/gradle/api/provider/Property;
2222
public final fun getGenerateDaggerFactories ()Lorg/gradle/api/provider/Property;
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package com.squareup.anvil.plugin
2+
3+
import com.rickbusarow.kase.Kase4
4+
import com.rickbusarow.kase.gradle.GradleDependencyVersion
5+
import com.rickbusarow.kase.gradle.GradleKotlinTestVersions
6+
import com.rickbusarow.kase.gradle.GradleProjectBuilder
7+
import com.rickbusarow.kase.gradle.HasGradleDependencyVersion
8+
import com.rickbusarow.kase.gradle.HasKotlinDependencyVersion
9+
import com.rickbusarow.kase.gradle.KotlinDependencyVersion
10+
import com.rickbusarow.kase.kase
11+
import com.rickbusarow.kase.times
12+
import io.kotest.matchers.string.shouldContain
13+
import org.junit.jupiter.api.DynamicNode
14+
import org.junit.jupiter.api.Nested
15+
import org.junit.jupiter.api.TestFactory
16+
import java.util.stream.Stream
17+
18+
class AnvilExtensionTest : BaseGradleTest() {
19+
20+
@Nested
21+
inner class `gradle property to extension property mapping` {
22+
23+
val properties = listOf(
24+
kase(a1 = "generateDaggerFactories", false),
25+
kase(a1 = "generateDaggerFactoriesOnly", false),
26+
kase(a1 = "disableComponentMerging", false),
27+
kase(a1 = "syncGeneratedSources", false),
28+
kase(a1 = "addOptionalAnnotations", false),
29+
)
30+
31+
fun GradleProjectBuilder.gradlePropertiesFile(propertyName: String, value: Any) {
32+
val props = buildList {
33+
if (propertyName == "generateDaggerFactoriesOnly") {
34+
// The "__FactoriesOnly" toggle requires the "__Factories" toggle to be enabled.
35+
add("com.squareup.anvil.generateDaggerFactories=true")
36+
}
37+
add("com.squareup.anvil.$propertyName=$value")
38+
}
39+
gradlePropertiesFile(props.joinToString("\n"))
40+
}
41+
42+
@TestFactory
43+
fun `extension properties are their default value when not set anywhere`() =
44+
tests { versions, propertyName, default ->
45+
46+
rootProject.buildFile(
47+
"""
48+
plugins {
49+
kotlin("jvm") version "${versions.kotlinVersion}"
50+
id("com.squareup.anvil") version "$anvilVersion"
51+
}
52+
53+
tasks.register("printProperty") {
54+
doLast {
55+
println("$propertyName: ${'$'}{anvil.$propertyName.get()}")
56+
}
57+
}
58+
""".trimIndent(),
59+
)
60+
61+
shouldSucceed("printProperty") {
62+
output shouldContain "$propertyName: $default"
63+
}
64+
}
65+
66+
@TestFactory
67+
fun `the extension property is not default when only set in gradle properties`() =
68+
tests { versions, propertyName, default ->
69+
rootProject {
70+
buildFile(
71+
"""
72+
plugins {
73+
kotlin("jvm") version "${versions.kotlinVersion}"
74+
id("com.squareup.anvil") version "$anvilVersion"
75+
}
76+
77+
tasks.register("printProperty") {
78+
doLast {
79+
println("$propertyName: ${'$'}{anvil.$propertyName.get()}")
80+
}
81+
}
82+
""".trimIndent(),
83+
)
84+
85+
gradlePropertiesFile(propertyName, !default)
86+
}
87+
88+
shouldSucceed("printProperty") {
89+
output shouldContain "$propertyName: ${!default}"
90+
}
91+
}
92+
93+
@TestFactory
94+
fun `the extension property is default when explicitly set to it in gradle properties`() =
95+
tests { versions, propertyName, default ->
96+
rootProject {
97+
buildFile(
98+
"""
99+
plugins {
100+
kotlin("jvm") version "${versions.kotlinVersion}"
101+
id("com.squareup.anvil") version "$anvilVersion"
102+
}
103+
104+
tasks.register("printProperty") {
105+
doLast {
106+
println("$propertyName: ${'$'}{anvil.$propertyName.get()}")
107+
}
108+
}
109+
""".trimIndent(),
110+
)
111+
112+
gradlePropertiesFile(propertyName, default)
113+
}
114+
115+
shouldSucceed("printProperty") {
116+
output shouldContain "$propertyName: $default"
117+
}
118+
}
119+
120+
@TestFactory
121+
fun `the extension property overrides the gradle properties value when set`() =
122+
tests { versions, propertyName, default ->
123+
124+
rootProject {
125+
val extensionText = if (propertyName == "generateDaggerFactoriesOnly") {
126+
"""
127+
anvil {
128+
generateDaggerFactories = true
129+
$propertyName = ${!default}
130+
}
131+
""".trimIndent()
132+
} else {
133+
"""
134+
anvil {
135+
$propertyName = ${!default}
136+
}
137+
""".trimIndent()
138+
}
139+
buildFile(
140+
"""
141+
plugins {
142+
kotlin("jvm") version "${versions.kotlinVersion}"
143+
id("com.squareup.anvil") version "$anvilVersion"
144+
}
145+
146+
tasks.register("printProperty") {
147+
doLast {
148+
println("$propertyName: ${'$'}{anvil.$propertyName.get()}")
149+
}
150+
}
151+
152+
$extensionText
153+
""".trimIndent(),
154+
)
155+
156+
gradlePropertiesFile(propertyName, default)
157+
}
158+
159+
shouldSucceed("printProperty") {
160+
output shouldContain "$propertyName: ${!default}"
161+
}
162+
}
163+
164+
inline fun tests(
165+
crossinline action: AnvilGradleTestEnvironment.(
166+
GradleKotlinTestVersions,
167+
String,
168+
Boolean,
169+
) -> Unit,
170+
): Stream<out DynamicNode> = params.asContainers { versions ->
171+
properties.times(listOf(versions), instanceFactory = ::PropertyKase)
172+
.asTests { kase -> action(versions, kase.propertyName, kase.default) }
173+
}
174+
}
175+
}
176+
177+
@PublishedApi
178+
internal class PropertyKase(
179+
val propertyName: String,
180+
val default: Boolean,
181+
override val gradle: GradleDependencyVersion,
182+
override val kotlin: KotlinDependencyVersion,
183+
) : Kase4<GradleDependencyVersion, KotlinDependencyVersion, String, Boolean> by kase(
184+
displayName = "property: $propertyName | default: $default",
185+
a1 = gradle,
186+
a2 = kotlin,
187+
a3 = propertyName,
188+
a4 = default,
189+
),
190+
GradleKotlinTestVersions,
191+
HasGradleDependencyVersion by HasGradleDependencyVersion(gradle),
192+
HasKotlinDependencyVersion by HasKotlinDependencyVersion(kotlin)

gradle-plugin/src/main/java/com/squareup/anvil/plugin/AnvilExtension.kt

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ package com.squareup.anvil.plugin
33
import org.gradle.api.Action
44
import org.gradle.api.model.ObjectFactory
55
import org.gradle.api.provider.Property
6+
import org.gradle.api.provider.ProviderFactory
67
import javax.inject.Inject
78

8-
public abstract class AnvilExtension @Inject constructor(objects: ObjectFactory) {
9+
public abstract class AnvilExtension @Inject constructor(
10+
objects: ObjectFactory,
11+
private val providers: ProviderFactory,
12+
) {
913
/**
1014
* Allows you to use Anvil to generate Factory classes that usually the Dagger annotation
1115
* processor would generate for @Provides methods, @Inject constructors and @Inject fields.
@@ -20,42 +24,74 @@ public abstract class AnvilExtension @Inject constructor(objects: ObjectFactory)
2024
* Java sources either.
2125
*
2226
* By default this feature is disabled.
27+
*
28+
* This property can also be set via a Gradle property:
29+
*
30+
* ```properties
31+
* com.squareup.anvil.generateDaggerFactories=true
32+
* ```
2333
*/
2434
public val generateDaggerFactories: Property<Boolean> = objects.property(Boolean::class.java)
25-
.convention(false)
35+
.conventionFromProperty("com.squareup.anvil.generateDaggerFactories", false)
2636

2737
/**
2838
* There are occasions where consumers of Anvil are only interested in generating Dagger
2939
* factories to speed up build times and don't want to make use of the other features. With this
3040
* flag Anvil will only generate Dagger factories and skip all other steps. If this flag is set
3141
* to `true`, then also [generateDaggerFactories] must be set to `true`.
42+
*
43+
* This property can also be set via a Gradle property:
44+
*
45+
* ```properties
46+
* com.squareup.anvil.generateDaggerFactoriesOnly=true
47+
* ```
3248
*/
3349
public val generateDaggerFactoriesOnly: Property<Boolean> = objects.property(Boolean::class.java)
34-
.convention(false)
50+
.conventionFromProperty("com.squareup.anvil.generateDaggerFactoriesOnly", false)
3551

3652
/**
3753
* Enabling this indicates that only code generation should run and no component merging should
3854
* run. This is useful for cases where you want to use `@ContributesTo`, `@ContributesBinding`,
3955
* or similar annotations but _not_ `@MergeComponent` or `@MergeSubcomponent` functionality.
4056
* This allows for anvil use in projects with kapt enabled but _not_ require disabling
4157
* incremental compilation in kapt stub generation tasks.
58+
*
59+
* This property can also be set via a Gradle property:
60+
*
61+
* ```properties
62+
* com.squareup.anvil.disableComponentMerging=true
63+
* ```
4264
*/
4365
public val disableComponentMerging: Property<Boolean> = objects.property(Boolean::class.java)
44-
.convention(false)
66+
.conventionFromProperty("com.squareup.anvil.disableComponentMerging", false)
4567

4668
/**
4769
* Add Anvil generated source directories to sourceSets in Gradle for indexing visibility in the
4870
* IDE. This can be useful in debugging and is disabled by default.
71+
*
72+
* This property can also be set via a Gradle property:
73+
*
74+
* ```properties
75+
* com.squareup.anvil.syncGeneratedSources=true
76+
* ```
4977
*/
5078
public val syncGeneratedSources: Property<Boolean> = objects.property(Boolean::class.java)
51-
.convention(false)
79+
.conventionFromProperty("com.squareup.anvil.syncGeneratedSources", false)
5280

5381
/**
54-
* Add the `annotations-optional` artifact as a dependency to make annotations like `@SingleIn` and `@ForScope`
55-
* available to use. These are annotations that are not strictly required but which we've found to be helpful with managing larger dependency graphs.
82+
* Add the `annotations-optional` artifact as a dependency to make annotations
83+
* like `@SingleIn` and `@ForScope` available to use. These are annotations
84+
* that are not strictly required but which we've found to be helpful with
85+
* managing larger dependency graphs.
86+
*
87+
* This property can also be set via a Gradle property:
88+
*
89+
* ```properties
90+
* com.squareup.anvil.addOptionalAnnotations=true
91+
* ```
5692
*/
5793
public val addOptionalAnnotations: Property<Boolean> = objects.property(Boolean::class.java)
58-
.convention(false)
94+
.conventionFromProperty("com.squareup.anvil.addOptionalAnnotations", false)
5995

6096
@Suppress("PropertyName")
6197
internal var _variantFilter: Action<VariantFilter>? = null
@@ -67,4 +103,13 @@ public abstract class AnvilExtension @Inject constructor(objects: ObjectFactory)
67103
public fun variantFilter(action: Action<VariantFilter>) {
68104
_variantFilter = action
69105
}
106+
107+
private fun Property<Boolean>.conventionFromProperty(
108+
name: String,
109+
default: Boolean,
110+
): Property<Boolean> = convention(
111+
providers.gradleProperty(name)
112+
.map(String::toBoolean)
113+
.orElse(default),
114+
)
70115
}

0 commit comments

Comments
 (0)