Dagger: @Binds with @IntoSet doesn't work in subcomponents in Dagger 2.5

Created on 23 Jun 2016  Â·  3Comments  Â·  Source: google/dagger

I have a component and a subcomponent that contribute elements to a single set. When using @Provides and @IntoSet, my component and subcomponent are returning all the expected elements. The following test shows that the subcomponent collects the elements that are provided in the component and the subcomponent:

public class ComponentTestsWithProvides {
    @Test
    public void testStringSet() {
        final TestComponent component = DaggerComponentTestsWithProvides_TestComponent.builder()
                .testComponentModule(new TestComponentModule())
                .build();
        final TestSubcomponent subcomponent = component.getTestSubcomponent(new TestSubcomponentModule());
        assertThat(component.getStrings())
                .containsOnly("Component");
        assertThat(subcomponent.getStrings())
                .containsOnly("Component", "Subcomponent");
    }

    @Qualifier
    public @interface ComponentQualifier {}

    @Component(modules = TestComponentModule.class)
    public interface TestComponent {
        Set<String> getStrings();
        TestSubcomponent getTestSubcomponent(TestSubcomponentModule module);
    }

    @Module
    public class TestComponentModule {
        @Provides
        @ComponentQualifier
        String provideString() {
            return "Component";
        }

        @Provides
        @IntoSet
        String provideStringIntoSet(@ComponentQualifier String string) {
            return string;
        }
    }

    @Qualifier
    public @interface SubcomponentQualifier {}

    @Subcomponent(modules = TestSubcomponentModule.class)
    public interface TestSubcomponent {
        Set<String> getStrings();
    }

    @Module
    public class TestSubcomponentModule {
        @Provides
        @SubcomponentQualifier
        String provideString() {
            return "Subcomponent";
        }

        @Provides
        @IntoSet
        String provideStringIntoSet(@SubcomponentQualifier String string) {
            return string;
        }
    }
}

Since the elements are provided by existing providers, I'd like to use @Binds instead of @Provides. The following code should have equivalent behavior, since it just replaces @Provides with @Binds:

public class ComponentTestsWithBinds {
    @Test
    public void testStringSet() {
        final TestComponent component = DaggerComponentTestsWithBinds_TestComponent.builder()
                .testComponentModule(new TestComponentModule())
                .build();
        final TestSubcomponent subcomponent = component.getTestSubcomponent(new TestSubcomponentModule());
        assertThat(component.getStrings())
                .containsOnly("Component");
        assertThat(subcomponent.getStrings())
                .containsOnly("Component", "Subcomponent");
    }

    @Qualifier
    public @interface ComponentQualifier {}

    @Component(modules = TestComponentModule.class)
    public interface TestComponent {
        Set<String> getStrings();
        TestSubcomponent getTestSubcomponent(TestSubcomponentModule module);
    }

    @Module(includes = TestComponentModule.Bindings.class)
    public static class TestComponentModule {
        @Provides
        @ComponentQualifier
        String provideString() {
            return "Component";
        }

        @Module
        public interface Bindings {
            @Binds
            @IntoSet
            String provideStringIntoSet(@ComponentQualifier String string);
        }
    }

    @Qualifier
    public @interface SubcomponentQualifier {}

    @Subcomponent(modules = TestSubcomponentModule.class)
    public interface TestSubcomponent {
        Set<String> getStrings();
    }

    @Module(includes = TestSubcomponentModule.Bindings.class)
    public static class TestSubcomponentModule {
        @Provides
        @SubcomponentQualifier
        String provideString() {
            return "Subcomponent";
        }

        @Module
        public interface Bindings {
            @Binds
            @IntoSet
            String provideStringIntoSet(@SubcomponentQualifier String string);
        }
    }
}

However, the subcomponent only returns "Component". Indeed, the implementation of TestSubcomponent.getStrings() does not use the subcomponent string provider:

    public Set<String> getStrings() {
      return DaggerComponentTestsWithBinds_TestComponent.this.setOfStringProvider.get();
    }

When using @Provides instead of @Binds, TestSubcomponent.getStrings() has the expected implementation:

    private void initialize() {

      this.provideStringProvider =
          ComponentTestsWithProvides_TestSubcomponentModule_ProvideStringFactory.create(
              testSubcomponentModule);

      this.provideStringIntoSetProvider =
          ComponentTestsWithProvides_TestSubcomponentModule_ProvideStringIntoSetFactory.create(
              testSubcomponentModule, provideStringProvider);

      this.setOfStringProvider =
          SetFactory.<String>builder(2, 0)
              .addProvider(
                  DaggerComponentTestsWithProvides_TestComponent.this.provideStringIntoSetProvider)
              .addProvider(provideStringIntoSetProvider)
              .build();
    }

    @Override
    public Set<String> getStrings() {
      return setOfStringProvider.get();
    }
  }
bug

Most helpful comment

Ah, good find. We're not detecting that as a subcomponent with local multibinding contributions. Thanks for alerting us, hope to have a fix soon!

All 3 comments

Ah, good find. We're not detecting that as a subcomponent with local multibinding contributions. Thanks for alerting us, hope to have a fix soon!

I have a request out for review, should definitely be synced out for Dagger 2.6 (or maybe even 2.5.1)

Ah, awesome, that was fast! :)

On Thu, Jun 23, 2016 at 3:30 PM, Ron Shapiro [email protected]
wrote:

I have a request out for review, should definitely be synced out for
Dagger 2.6 (or maybe even 2.5.1)

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/google/dagger/issues/401#issuecomment-228205301, or mute
the thread
https://github.com/notifications/unsubscribe/ACZo0G8Eu9vnkRqJkUcej-yDi6M4iYaMks5qOwkggaJpZM4I8XGP
.

Was this page helpful?
0 / 5 - 0 ratings