com.squareup.anvil.annotations.ContributesSubcomponent.kt Maven / Gradle / Ivy
package com.squareup.anvil.annotations
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.annotation.AnnotationTarget.CLASS
import kotlin.reflect.KClass
/**
* Similar to [MergeSubcomponent], but with the main difference that the subcomponent is generated
* and modules, bindings and component interfaces are merged whenever the component with
* [parentScope] is processed.
*
* Imagine this module dependency tree:
* ```
* :app
* / \
* v v
* :lib-a :lib-b
* ```
* `:app` creates the component with `@MergeComponent`, `:lib-a` creates a subcomponent with
* `@MergeSubcomponent` and `:lib-b` contributes a module to the scope of the subcomponent. This
* module won't be included in the subcomponent without adding the dependency `:lib-a -> :lib-b`.
* See [MergeSubcomponent] for further explanation.
*
* On the other hand, if `:lib-a` uses `@ContributesSubcomponent` with a parent scope of the main
* component from `:app`, then the actual subcomponent will be generated in the `:app` module and
* the contributed module from `:lib-b` will be picked up.
*
* ```
* @ContributesSubcomponent(
* scope = ActivityScope::class,
* parentScope = AppScope::class
* )
* interface ActivitySubcomponent
* ```
*
* [parentScope] can be the scope of a [MergeComponent], [MergeSubcomponent] or another
* [ContributesSubcomponent]. A chain of [ContributesSubcomponent]s is supported.
*
* It's possible to exclude any automatically added Dagger module or component interface with the
* [exclude] parameter if needed.
* ```
* @ContributesSubcomponent(
* scope = ActivityScope::class,
* parentScope = AppScope::class,
* exclude = [
* DaggerModule::class,
* ComponentInterface::class
* ]
* )
* interface ActivitySubcomponent
* ```
*
* It's recommended to define a parent component interface as inner class of the contributed
* subcomponent that is contributed to the parent scope. Anvil will always generate a parent
* component interface for the final generated subcomponent with an abstract factory method for
* the subcomponent. If you create your own parent component interface, then the one generated by
* Anvil will extend your interface. E.g.
* ```
* @ContributesSubcomponent(
* scope = ActivityScope::class,
* parentScope = AppScope::class
* )
* interface ActivitySubcomponent {
*
* @ContributesTo(AppScope::class)
* interface ParentComponent {
* fun createActivitySubcomponent(): ActivitySubcomponent
* }
* }
* ```
*/
@Target(CLASS)
@Retention(RUNTIME)
public annotation class ContributesSubcomponent(
/**
* The scope used to find all contributed bindings, multibindings, modules and component
* interfaces, which should be included in this subcomponent.
*/
val scope: KClass<*>,
/**
* The actual subcomponent for this contributed subcomponent will be generated when a
* [MergeComponent], [MergeSubcomponent] or another [ContributesSubcomponent] annotated component
* with the same scope as `parentScope` is merged.
*/
val parentScope: KClass<*>,
/**
* List of Dagger modules that should be manually included in the subcomponent and aren't
* automatically contributed.
*/
val modules: Array> = [],
/**
* List of bindings, multibindings, modules and component interfaces that are contributed to the
* same scope, but should be excluded from the subcomponent.
*/
val exclude: Array> = [],
/**
* This contributed subcomponent will replace these contributed subcomponents. All replaced
* subcomponents must use the same scope.
*/
val replaces: Array> = []
) {
/**
* A factory for a contributed subcomponent.
*
* This follows all the rules of `Subcomponent.Factory`, except it must appear in classes
* annotated with `@ContributesSubcomponent` instead of `@Subcomponent`.
*
* It's strongly recommended creating a parent component interface next to the factory that is
* contributed to the parent scope. The parent component interface should have one method that
* returns the factory type, e.g.
* ```
* @ContributesSubcomponent(
* scope = ActivityScope::class,
* parentScope = AppScope::class
* )
* interface ActivitySubcomponent {
*
* @ContributesSubcomponent.Factory
* interface Factory {
* fun createActivitySubcomponent(
* @BindsInstance int: Int
* ): ActivitySubcomponent
* }
*
* @ContributesTo(AppScope::class)
* interface ParentComponent {
* fun createActivitySubcomponentFactory(): ActivitySubcomponent.Factory
* }
* }
* ```
* If no parent component interface but a factory is present, then the automatically generated
* parent component interface will return a type of the factory and not the subcomponent
* directly.
*/
public annotation class Factory
}