square / anvil

A Kotlin compiler plugin to make dependency injection with Dagger 2 easier.
Apache License 2.0
1.31k stars 80 forks source link

`ContributesBinding` or `ContributesMultibinding` on an `object` declaration requires some sort of Dagger factory generation #948

Closed RBusarow closed 5 months ago

RBusarow commented 6 months ago

This is new as of 2.5.0-beta04.

When these are all true

Then

There will be an unresolved reference to a ***_Provide***Factory in the Dagger-generated component implementation (in a downstream Gradle module).

Fix

Simply enable factory generation via Anvil's generateDaggerFactories, or by using Dagger with KAPT or KSP.


Given a declaration like:

package bar

// imports

@ContributesBinding(Scope::class) // or @ContributesMultibinding
object FooImpl : Foo

Anvil will now generate this is in the same package:

package bar

// imports

@Module
@ContributesTo(scope = Scope::class)
@InternalBindingMarker(
  originClass = Foo::class,
  isMultibinding = false,
  priority = "NORMAL",
)
public object FooImplAsBarFooToBarScopeBindingModule {
  @Provides
  public fun provideFoo(): Foo = FooImpl
}

That @Provides function must have a corresponding generated factory, or there will be an unresolved reference in the generated downstream component class.

package bar.app;

import bar.FooImplAsBarFooToBarScopeBindingModule_ProvideFooFactory;  //  this is unresolved
import bar.Foo;
import dagger.internal.DaggerGenerated;
import javax.annotation.processing.Generated;

@DaggerGenerated
@Generated(
    value = "dagger.internal.codegen.ComponentProcessor",
    comments = "https://dagger.dev"
)
public final class DaggerComponentInterface {

  // ...

  @Override
  public Foo foo() {
           // this is also unresolved
    return FooImplAsBarFooToBarScopeBindingModule_ProvideFooFactory.provideFoo();
  }
}