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

Option to limit Dagger factory generation to specific source sets #727

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ sources either.
When you enable this feature, don't forget to remove the Dagger annotation processor. You should
keep all other dependencies.

If you want to only enable Dagger factory generation on some source sets
(such as only in main source set or only in tests), you can add those source sets
to the allowlist:

```groovy
anvil {
generateDaggerFactoriesSourceSetAllowlist.add("main")
}
```


## Extending Anvil

Every codebase has its own dependency injection patterns where certain code structures need to be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.squareup.anvil.plugin

import org.gradle.api.Action
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import javax.inject.Inject

Expand Down Expand Up @@ -33,6 +34,15 @@ public abstract class AnvilExtension @Inject constructor(objects: ObjectFactory)
public val generateDaggerFactoriesOnly: Property<Boolean> = objects.property(Boolean::class.java)
.convention(false)

/**
* Allowlist of all source sets (such as main, test etc.) that Anvil should generate dagger
* factories in, if factory generation is enabled.
*
* When empty, Anvil will generate factories in all source sets.
*/
public var generateDaggerFactoriesSourceSetAllowlist: ListProperty<String> =
objects.listProperty(String::class.java)

/**
* Enabling this indicates that only code generation should run and no component merging should
* run. This is useful for cases where you want to use `@ContributesTo`, `@ContributesBinding`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0
import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask
Expand All @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.androidJvm
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
Expand Down Expand Up @@ -170,6 +172,23 @@ internal open class AnvilPlugin : KotlinCompilerPluginSupportPlugin {
}
}

val allowlistedVariants = variant.variantFilter
.generateDaggerFactoriesSourceSetAllowlist.map { sourceSetName ->
val sourceSet = variant.kotlinSourceSets.singleOrNull { it.name == sourceSetName }
?: throw GradleException("Unknown variant $sourceSetName. Available variants: " +
"${variant.kotlinSourceSets.joinToString { it.name }}"
)

sourceSet
}

val enableDaggerFactoriesInThisVariant = allowlistedVariants.isEmpty() ||
variant.androidSourceSets?.any { androidSourceSet ->
allowlistedVariants.any { allowlistedSourceSet ->
allowlistedSourceSet.name == androidSourceSet.name
}
} == true

return project.provider {
listOf(
FilesSubpluginOption(
Expand All @@ -178,11 +197,13 @@ internal open class AnvilPlugin : KotlinCompilerPluginSupportPlugin {
),
SubpluginOption(
key = "generate-dagger-factories",
lazy { variant.variantFilter.generateDaggerFactories.toString() }
lazy { (variant.variantFilter.generateDaggerFactories &&
enableDaggerFactoriesInThisVariant).toString() }
),
SubpluginOption(
key = "generate-dagger-factories-only",
lazy { variant.variantFilter.generateDaggerFactoriesOnly.toString() }
lazy { (variant.variantFilter.generateDaggerFactoriesOnly &&
enableDaggerFactoriesInThisVariant).toString() }
),
SubpluginOption(
key = "disable-component-merging",
Expand Down Expand Up @@ -359,6 +380,7 @@ internal class Variant private constructor(
val compileTaskProvider: TaskProvider<KotlinCompile>,
val androidVariant: BaseVariant?,
val androidSourceSets: List<AndroidSourceSet>?,
val kotlinSourceSets: List<KotlinSourceSet>,
val compilerPluginClasspathName: String,
val variantFilter: VariantFilter,
) {
Expand Down Expand Up @@ -391,6 +413,8 @@ internal class Variant private constructor(
null
}

val kotlinSourceSets = project.kotlinExtension.sourceSets.toList()

val commonFilter = CommonFilter(kotlinCompilation.name, extension)
val variantFilter = if (androidVariant != null) {
AndroidVariantFilter(commonFilter, androidVariant)
Expand All @@ -406,6 +430,7 @@ internal class Variant private constructor(
TaskProvider<KotlinCompile>,
androidVariant = androidVariant,
androidSourceSets = androidSourceSets,
kotlinSourceSets = kotlinSourceSets,
compilerPluginClasspathName = PLUGIN_CLASSPATH_CONFIGURATION_NAME +
kotlinCompilation.target.targetName.replaceFirstChar(Char::uppercase) +
kotlinCompilation.name.replaceFirstChar(Char::uppercase),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public interface VariantFilter : Named {
*/
public var generateDaggerFactoriesOnly: Boolean

/**
* Allowlist of all source sets (such as main, test etc.) that Anvil should generate dagger
* factories in, if factory generation is enabled.
*
* When empty, Anvil will generate factories in all source sets.
*/
public var generateDaggerFactoriesSourceSetAllowlist: List<String>

/**
* Indicate whether component merging for this variant should be disabled. The default
* value comes from the [AnvilExtension]. See [AnvilExtension.disableComponentMerging] for more
Expand Down Expand Up @@ -66,6 +74,14 @@ internal class CommonFilter(
generateDaggerFactoriesOnlyOverride = value
}

private var generateDaggerFactoriesSourceSetAllowOverride: List<String>? = null
override var generateDaggerFactoriesSourceSetAllowlist: List<String>
get() = generateDaggerFactoriesSourceSetAllowOverride
?: extension.generateDaggerFactoriesSourceSetAllowlist.get()
set(value) {
generateDaggerFactoriesSourceSetAllowOverride = value
}

private var disableComponentMergingOverride: Boolean? = null
override var disableComponentMerging: Boolean
get() = disableComponentMergingOverride ?: extension.disableComponentMerging.get()
Expand Down