blob: cb67eb05548c1c5f2018bd39c5302c9c4d33d042 [file] [log] [blame]
/*
* Copyright (C) 2018 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.internal.codegen;
import static com.google.testing.compile.CompilationSubject.assertThat;
import static dagger.internal.codegen.CompilerMode.AHEAD_OF_TIME_SUBCOMPONENTS_MODE;
import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
import static dagger.internal.codegen.Compilers.daggerCompiler;
import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
import com.google.common.collect.ImmutableList;
import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
import javax.tools.JavaFileObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class AheadOfTimeSubcomponentsTest {
private static final String PRUNED_METHOD_BODY =
"throw new UnsupportedOperationException(\"This binding is not part of the final binding "
+ "graph. The key was requested by a binding that was believed to possibly be part of "
+ "the graph, but is no longer requested. If this exception is thrown, it is the result "
+ "of a Dagger bug.\");";
@Test
public void missingBindings_fromComponentMethod() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" MissingInLeaf missingFromComponentMethod();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public final MissingInLeaf missingFromComponentMethod() {",
" return AncestorModule_SatisfiedInAncestorFactory.proxySatisfiedInAncestor();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void missingBindings_dependsOnBindingWithMatchingComponentMethod() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" MissingInLeaf missingComponentMethod();",
" DependsOnComponentMethod dependsOnComponentMethod();",
"}"),
JavaFileObjects.forSourceLines(
"test.DependsOnComponentMethod",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class DependsOnComponentMethod {",
" @Inject DependsOnComponentMethod(MissingInLeaf missingInLeaf) {}",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public DependsOnComponentMethod dependsOnComponentMethod() {",
" return new DependsOnComponentMethod(missingComponentMethod());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
}
@Test
public void missingBindings_dependsOnMissingBinding() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" DependsOnMissingBinding dependsOnMissingBinding();",
"}"),
JavaFileObjects.forSourceLines(
"test.DependsOnMissingBinding",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class DependsOnMissingBinding {",
" @Inject DependsOnMissingBinding(MissingInLeaf missing) {}",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public DependsOnMissingBinding dependsOnMissingBinding() {",
" return DependsOnMissingBinding_Factory.newDependsOnMissingBinding(",
" getMissingInLeaf());",
" }",
"",
" protected abstract Object getMissingInLeaf();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" protected final Object getMissingInLeaf() {",
" return AncestorModule_SatisfiedInAncestorFactory.proxySatisfiedInAncestor();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void missingBindings_satisfiedInGreatAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" DependsOnMissingBinding dependsOnMissingBinding();",
"}"),
JavaFileObjects.forSourceLines(
"test.DependsOnMissingBinding",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class DependsOnMissingBinding {",
" @Inject DependsOnMissingBinding(MissingInLeaf missing) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.GreatAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = SatisfiesMissingBindingModule.class)",
"interface GreatAncestor {",
" Ancestor ancestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.SatisfiesMissingBindingModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class SatisfiesMissingBindingModule {",
" @Provides",
" static MissingInLeaf satisfy() { return new MissingInLeaf(); }",
"}"));
// DaggerLeaf+DaggerAncestor generated types are ignored - they're not the focus of this test
// and are tested elsewhere
JavaFileObject generatedGreatAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGreatAncestor implements GreatAncestor {",
" protected DaggerGreatAncestor() {}",
"",
" protected abstract class AncestorImpl extends DaggerAncestor {",
" protected AncestorImpl() {}",
"",
" protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
" protected LeafImpl() {}",
"",
" @Override",
" protected final Object getMissingInLeaf() {",
" return SatisfiesMissingBindingModule_SatisfyFactory.proxySatisfy();",
" }",
" }",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGreatAncestor")
.hasSourceEquivalentTo(generatedGreatAncestor);
}
@Test
public void moduleInstanceDependency() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = TestModule.class)",
"interface Leaf {",
" String string();",
"}"),
JavaFileObjects.forSourceLines(
"test.TestModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class TestModule {",
" @Provides String provideString() { return \"florp\"; }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public String string() {",
" return TestModule_ProvideStringFactory.proxyProvideString(testModule());",
" }",
"",
" protected abstract TestModule testModule();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Ancestor ancestor();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Ancestor ancestor() {",
" return new AncestorImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class AncestorImpl extends DaggerAncestor {",
" private AncestorImpl() {}",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" private TestModule testModule;",
"",
" private LeafImpl() {",
" this.testModule = new TestModule();",
" }",
"",
" @Override",
" protected TestModule testModule() {",
" return testModule;",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void moduleInstanceDependency_withModuleParams() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = TestModule.class)",
"interface Leaf {",
" int getInt();",
"}"),
JavaFileObjects.forSourceLines(
"test.TestModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"final class TestModule {",
" private int i;",
"",
" TestModule(int i) {}",
"",
" @Provides int provideInt() {",
" return i++;",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public int getInt() {",
" return testModule().provideInt();",
" }",
"",
" protected abstract TestModule testModule();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf(TestModule module);",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Ancestor ancestor();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Ancestor ancestor() {",
" return new AncestorImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class AncestorImpl extends DaggerAncestor {",
" private AncestorImpl() {}",
"",
" @Override",
" public Leaf leaf(TestModule module) {",
" Preconditions.checkNotNull(module);",
" return new LeafImpl(module);",
" }",
"",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" private TestModule testModule;",
"",
" private LeafImpl(TestModule module) {",
" this.testModule = module;",
" }",
"",
" @Override",
" protected TestModule testModule() {",
" return testModule;",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void generatedInstanceBinding() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" @Subcomponent.Builder",
" interface Builder {",
" Leaf build();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" public abstract static class Builder implements Leaf.Builder {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf.Builder leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Ancestor ancestor();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Ancestor ancestor() {",
" return new AncestorImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class AncestorImpl extends DaggerAncestor {",
" private AncestorImpl() {}",
"",
" @Override",
" public Leaf.Builder leaf() {",
" return new LeafBuilder();",
" }",
"",
" private final class LeafBuilder extends DaggerLeaf.Builder {",
" @Override",
" public Leaf build() {",
" return new LeafImpl();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" private LeafImpl() {}",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void prunedGeneratedInstanceBinding() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.PrunedSubcomponent",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface PrunedSubcomponent {",
" @Subcomponent.Builder",
" interface Builder {",
" PrunedSubcomponent build();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.InstallsPrunedSubcomponentModule",
"package test;",
"",
"import dagger.Module;",
"",
"@Module(subcomponents = PrunedSubcomponent.class)",
"interface InstallsPrunedSubcomponentModule {}"),
JavaFileObjects.forSourceLines(
"test.DependsOnPrunedSubcomponentBuilder",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class DependsOnPrunedSubcomponentBuilder {",
" @Inject DependsOnPrunedSubcomponentBuilder(PrunedSubcomponent.Builder builder) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.MaybeLeaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = InstallsPrunedSubcomponentModule.class)",
"interface MaybeLeaf {",
" DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder();",
"}"));
JavaFileObject generatedMaybeLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerMaybeLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerMaybeLeaf implements MaybeLeaf {",
" protected DaggerMaybeLeaf() {}",
"",
" @Override",
" public DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder() {",
" return DependsOnPrunedSubcomponentBuilder_Factory",
" .newDependsOnPrunedSubcomponentBuilder(",
" getPrunedSubcomponentBuilder());",
" }",
"",
" protected abstract Object getPrunedSubcomponentBuilder();",
"",
" protected abstract class PrunedSubcomponentImpl extends DaggerPrunedSubcomponent {",
" protected PrunedSubcomponentImpl() {}",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerMaybeLeaf")
.hasSourceEquivalentTo(generatedMaybeLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.PrunesGeneratedInstanceModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"interface PrunesGeneratedInstanceModule {",
" @Provides",
" static DependsOnPrunedSubcomponentBuilder pruneGeneratedInstance() {",
" return new DependsOnPrunedSubcomponentBuilder(null);",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = PrunesGeneratedInstanceModule.class)",
"interface Root {",
" MaybeLeaf actuallyLeaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public MaybeLeaf actuallyLeaf() {",
" return new MaybeLeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class MaybeLeafImpl extends DaggerMaybeLeaf {",
" private MaybeLeafImpl() {}",
"",
" @Override",
" protected Object getPrunedSubcomponentBuilder() {",
" " + PRUNED_METHOD_BODY,
" }",
"",
" @Override",
" public DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder() {",
" return PrunesGeneratedInstanceModule_PruneGeneratedInstanceFactory",
" .proxyPruneGeneratedInstance();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void optionalBindings_boundAndSatisfiedInSameSubcomponent() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "SatisfiedInSub");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Sub",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Optional;",
"",
"@Subcomponent(modules = {SubModule.class, BindsSatisfiedInSubModule.class})",
"interface Sub {",
" Optional<SatisfiedInSub> satisfiedInSub();",
"}"),
JavaFileObjects.forSourceLines(
"test.SubModule",
"package test;",
"",
"import dagger.BindsOptionalOf;",
"import dagger.Module;",
"",
"@Module",
"abstract class SubModule {",
" @BindsOptionalOf abstract SatisfiedInSub optionalSatisfiedInSub();",
"}"),
JavaFileObjects.forSourceLines(
"test.BindsSatisfiedInSubModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"abstract class BindsSatisfiedInSubModule {",
" @Provides static SatisfiedInSub provideSatisfiedInSub() {",
" return new SatisfiedInSub();",
" }",
"}"));
JavaFileObject generatedSubcomponent =
JavaFileObjects.forSourceLines(
"test.DaggerSub",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerSub implements Sub {",
" protected DaggerSub() {}",
"",
" @Override",
" public Optional<SatisfiedInSub> satisfiedInSub() {",
" return Optional.of(",
" BindsSatisfiedInSubModule_ProvideSatisfiedInSubFactory",
" .proxyProvideSatisfiedInSub());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerSub")
.hasSourceEquivalentTo(generatedSubcomponent);
}
@Test
public void optionalBindings_satisfiedInAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "SatisfiedInAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Optional;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Optional<SatisfiedInAncestor> satisfiedInAncestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.BindsOptionalOf;",
"import dagger.Module;",
"",
"@Module",
"abstract class LeafModule {",
" @BindsOptionalOf abstract SatisfiedInAncestor optionalSatisfiedInAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Optional<SatisfiedInAncestor> satisfiedInAncestor() {",
" return Optional.<SatisfiedInAncestor>empty();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"abstract class AncestorModule {",
" @Provides",
" static SatisfiedInAncestor satisfiedInAncestor(){",
" return new SatisfiedInAncestor();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public final Optional<SatisfiedInAncestor> satisfiedInAncestor() {",
" return Optional.of(AncestorModule_SatisfiedInAncestorFactory",
" .proxySatisfiedInAncestor());",
" }",
"",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void optionalBindings_satisfiedInGrandAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "SatisfiedInGrandAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Optional;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.BindsOptionalOf;",
"import dagger.Module;",
"",
"@Module",
"abstract class LeafModule {",
" @BindsOptionalOf",
" abstract SatisfiedInGrandAncestor optionalSatisfiedInGrandAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor() {",
" return Optional.<SatisfiedInGrandAncestor>empty();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.GreatAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = GreatAncestorModule.class)",
"interface GreatAncestor {",
" Ancestor ancestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.GreatAncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"abstract class GreatAncestorModule {",
" @Provides",
" static SatisfiedInGrandAncestor satisfiedInGrandAncestor(){",
" return new SatisfiedInGrandAncestor();",
" }",
"}"));
JavaFileObject generatedGreatAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerGreatAncestor",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGreatAncestor implements GreatAncestor {",
" protected DaggerGreatAncestor() {}",
"",
" protected abstract class AncestorImpl extends DaggerAncestor {",
" protected AncestorImpl() {}",
"",
" protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
" protected LeafImpl() {}",
"",
" @Override",
" public final Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor() {",
" return Optional.of(",
" GreatAncestorModule_SatisfiedInGrandAncestorFactory",
" .proxySatisfiedInGrandAncestor());",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGreatAncestor")
.hasSourceEquivalentTo(generatedGreatAncestor);
}
@Test
public void optionalBindings_nonComponentMethodDependencySatisfiedInAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(
filesToCompile, "SatisfiedInAncestor", "RequiresOptionalSatisfiedInAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Optional;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" RequiresOptionalSatisfiedInAncestor requiresOptionalSatisfiedInAncestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.BindsOptionalOf;",
"import dagger.Module;",
"import dagger.Provides;",
"import java.util.Optional;",
"",
"@Module",
"abstract class LeafModule {",
" @Provides static RequiresOptionalSatisfiedInAncestor",
" provideRequiresOptionalSatisfiedInAncestor(",
" Optional<SatisfiedInAncestor> satisfiedInAncestor) {",
" return new RequiresOptionalSatisfiedInAncestor();",
" }",
"",
" @BindsOptionalOf abstract SatisfiedInAncestor optionalSatisfiedInAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public RequiresOptionalSatisfiedInAncestor",
" requiresOptionalSatisfiedInAncestor() {",
" return LeafModule_ProvideRequiresOptionalSatisfiedInAncestorFactory",
" .proxyProvideRequiresOptionalSatisfiedInAncestor(",
" getOptionalOfSatisfiedInAncestor());",
" }",
"",
" protected Optional getOptionalOfSatisfiedInAncestor() {",
" return Optional.<SatisfiedInAncestor>empty();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"abstract class AncestorModule {",
" @Provides",
" static SatisfiedInAncestor satisfiedInAncestor(){",
" return new SatisfiedInAncestor();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" protected final Optional getOptionalOfSatisfiedInAncestor() {",
" return Optional.of(",
" AncestorModule_SatisfiedInAncestorFactory.proxySatisfiedInAncestor());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void optionalBindings_boundInAncestorAndSatisfiedInGrandAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "SatisfiedInGrandAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Optional;",
"",
"@Subcomponent",
"interface Leaf {",
" Optional<SatisfiedInGrandAncestor> boundInAncestorSatisfiedInGrandAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.BindsOptionalOf;",
"import dagger.Module;",
"",
"@Module",
"abstract class AncestorModule {",
" @BindsOptionalOf",
" abstract SatisfiedInGrandAncestor optionalSatisfiedInGrandAncestor();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Optional<SatisfiedInGrandAncestor>",
" boundInAncestorSatisfiedInGrandAncestor() {",
" return Optional.<SatisfiedInGrandAncestor>empty();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.GrandAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = GrandAncestorModule.class)",
"interface GrandAncestor {",
" Ancestor ancestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.GrandAncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class GrandAncestorModule {",
" @Provides static SatisfiedInGrandAncestor provideSatisfiedInGrandAncestor() {",
" return new SatisfiedInGrandAncestor();",
" }",
"}"));
JavaFileObject generatedGrandAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerGrandAncestor",
"package test;",
"",
"import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGrandAncestor implements GrandAncestor {",
" protected DaggerGrandAncestor() {}",
"",
" protected abstract class AncestorImpl extends DaggerAncestor {",
" protected AncestorImpl() {}",
"",
" protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
" protected LeafImpl() {}",
"",
" @Override",
" public final Optional<SatisfiedInGrandAncestor>",
" boundInAncestorSatisfiedInGrandAncestor() {",
" return Optional.of(",
" GrandAncestorModule_ProvideSatisfiedInGrandAncestorFactory",
" .proxyProvideSatisfiedInGrandAncestor());",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGrandAncestor")
.hasSourceEquivalentTo(generatedGrandAncestor);
}
@Test
public void setMultibindings_contributionsInLeaf() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<InLeaf> contributionsInLeaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static InLeaf provideInLeaf() {",
" return new InLeaf();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<InLeaf> contributionsInLeaf() {",
" return ImmutableSet.<InLeaf>of(",
" LeafModule_ProvideInLeafFactory.proxyProvideInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
}
@Test
public void setMultibindings_contributionsInAncestorOnly() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent",
"interface Leaf {",
" Set<InAncestor> contributionsInAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.ElementsIntoSet;",
"import java.util.Set;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @ElementsIntoSet",
" static Set<InAncestor> provideInAncestors() {",
" return ImmutableSet.of(new InAncestor(), new InAncestor());",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Set<InAncestor> contributionsInAncestor() {",
" return ImmutableSet.<InAncestor>copyOf(",
" AncestorModule_ProvideInAncestorsFactory.proxyProvideInAncestors());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void setMultibindings_contributionsInLeafAndAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InEachSubcomponent");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<InEachSubcomponent> contributionsInEachSubcomponent();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static InEachSubcomponent provideInLeaf() {",
" return new InEachSubcomponent();",
" }",
"",
" @Provides",
" @IntoSet",
" static InEachSubcomponent provideAnotherInLeaf() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
" return ImmutableSet.<InEachSubcomponent>of(",
" LeafModule_ProvideInLeafFactory.proxyProvideInLeaf(),",
" LeafModule_ProvideAnotherInLeafFactory.proxyProvideAnotherInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.ElementsIntoSet;",
"import java.util.Set;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @ElementsIntoSet",
" static Set<InEachSubcomponent> provideInAncestor() {",
" return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
" return ImmutableSet.<InEachSubcomponent>builderWithExpectedSize(3)",
" .addAll(AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor())",
" .addAll(super.contributionsInEachSubcomponent())",
" .build();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void setMultibindings_contributionsInLeafAndGrandAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InLeafAndGrandAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static InLeafAndGrandAncestor provideInLeaf() {",
" return new InLeafAndGrandAncestor();",
" }",
"",
" @Provides",
" @IntoSet",
" static InLeafAndGrandAncestor provideAnotherInLeaf() {",
" return new InLeafAndGrandAncestor();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
" return ImmutableSet.<InLeafAndGrandAncestor>of(",
" LeafModule_ProvideInLeafFactory.proxyProvideInLeaf(),",
" LeafModule_ProvideAnotherInLeafFactory.proxyProvideAnotherInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.GrandAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = GrandAncestorModule.class)",
"interface GrandAncestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.GrandAncestorModule",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.ElementsIntoSet;",
"import java.util.Set;",
"",
"@Module",
"class GrandAncestorModule {",
" @Provides",
" @ElementsIntoSet",
" static Set<InLeafAndGrandAncestor> provideInGrandAncestor() {",
" return ImmutableSet.of(new InLeafAndGrandAncestor(),",
" new InLeafAndGrandAncestor());",
" }",
"}"));
JavaFileObject generatedGrandAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerGrandAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGrandAncestor implements GrandAncestor {",
" protected DaggerGrandAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
" return ImmutableSet.<InLeafAndGrandAncestor>builderWithExpectedSize(3)",
" .addAll(GrandAncestorModule_ProvideInGrandAncestorFactory",
" .proxyProvideInGrandAncestor())",
" .addAll(super.contributionsInLeafAndGrandAncestor())",
" .build();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGrandAncestor")
.hasSourceEquivalentTo(generatedGrandAncestor);
}
@Test
public void setMultibindings_nonComponentMethodDependency() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InAllSubcomponents", "RequresInAllSubcomponentsSet");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" RequresInAllSubcomponentsSet requiresNonComponentMethod();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"import java.util.Set;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static InAllSubcomponents provideInAllSubcomponents() {",
" return new InAllSubcomponents();",
" }",
"",
" @Provides",
" static RequresInAllSubcomponentsSet providesRequresInAllSubcomponentsSet(",
" Set<InAllSubcomponents> inAllSubcomponents) {",
" return new RequresInAllSubcomponentsSet();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public RequresInAllSubcomponentsSet requiresNonComponentMethod() {",
" return LeafModule_ProvidesRequresInAllSubcomponentsSetFactory",
" .proxyProvidesRequresInAllSubcomponentsSet(getSetOfInAllSubcomponents());",
" }",
"",
" protected Set getSetOfInAllSubcomponents() {",
" return ImmutableSet.<InAllSubcomponents>of(",
" LeafModule_ProvideInAllSubcomponentsFactory",
" .proxyProvideInAllSubcomponents());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoSet",
" static InAllSubcomponents provideInAllSubcomponents() {",
" return new InAllSubcomponents();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" protected Set getSetOfInAllSubcomponents() {",
" return ImmutableSet.<InAllSubcomponents>builderWithExpectedSize(2)",
" .add(AncestorModule_ProvideInAllSubcomponentsFactory",
" .proxyProvideInAllSubcomponents())",
" .addAll(super.getSetOfInAllSubcomponents())",
" .build();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void setMultibindings_newSubclass() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InAncestor", "RequiresInAncestorSet");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" RequiresInAncestorSet missingWithSetDependency();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"import java.util.Set;",
"",
"@Module",
"class AncestorModule {",
"",
" @Provides",
" static RequiresInAncestorSet provideRequiresInAncestorSet(",
" Set<InAncestor> inAncestors) {",
" return new RequiresInAncestorSet();",
" }",
"",
" @Provides",
" @IntoSet",
" static InAncestor provideInAncestor() {",
" return new InAncestor();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
// TODO(b/117833324): because this is a private method, the return type shouldn't need
// to be the publicly accessible type. This may be easier to detect if we fold
// BindingMethodImplementation into MethodBindingExpression
" private Object getRequiresInAncestorSet() {",
" return AncestorModule_ProvideRequiresInAncestorSetFactory",
" .proxyProvideRequiresInAncestorSet(getSetOfInAncestor());",
" }",
"",
" protected Set getSetOfInAncestor() {",
" return ImmutableSet.<InAncestor>of(",
" AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor());",
" }",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public final RequiresInAncestorSet missingWithSetDependency() {",
" return (RequiresInAncestorSet) DaggerAncestor.this.getRequiresInAncestorSet();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void setMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(
filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<Multibound> instance();",
" MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"import java.util.Set;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static Multibound contribution() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<Multibound> instance() {",
" return ImmutableSet.<Multibound>of(",
" LeafModule_ContributionFactory.proxyContribution());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.Multibinds;",
"import java.util.Set;",
"import javax.inject.Provider;",
"",
"@Module",
"interface AncestorModule {",
" @Provides",
" static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
" Provider<Set<Multibound>> frameworkInstance) {",
" return null;",
" }",
"",
" @Multibinds Set<Multibound> multibinds();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Set<Multibound>> setOfMultiboundProvider;",
"",
" protected LeafImpl() {}",
"",
" protected void configureInitialization() { ",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() { ",
" this.setOfMultiboundProvider =",
" SetFactory.<Multibound>builder(1, 0)",
" .addProvider(LeafModule_ContributionFactory.create())",
" .build();",
" }",
"",
" protected Provider getSetOfMultiboundProvider() {",
" return setOfMultiboundProvider;",
" }",
"",
" @Override",
" public final MissingInLeaf_WillDependOnFrameworkInstance ",
" willDependOnFrameworkInstance() {",
" return AncestorModule_ProvidedInAncestorFactory.proxyProvidedInAncestor(",
" getSetOfMultiboundProvider());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void setMultibindings_contributionsInLeafAndAncestor_frameworkInstances() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InEachSubcomponent");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoSet",
" static InEachSubcomponent provideInLeaf() {",
" return new InEachSubcomponent();",
" }",
"",
" @Provides",
" @IntoSet",
" static InEachSubcomponent provideAnotherInLeaf() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.setOfInEachSubcomponentProvider =",
" SetFactory.<InEachSubcomponent>builder(2, 0)",
" .addProvider(LeafModule_ProvideInLeafFactory.create())",
" .addProvider(LeafModule_ProvideAnotherInLeafFactory.create())",
" .build();",
" }",
"",
" @Override",
" public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
" return setOfInEachSubcomponentProvider;",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.ElementsIntoSet;",
"import java.util.Set;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @ElementsIntoSet",
" static Set<InEachSubcomponent> provideInAncestor() {",
" return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider = ",
" new DelegateFactory<>();",
"",
" protected LeafImpl() {}",
"",
" @Override",
" protected void configureInitialization() {",
" super.configureInitialization();",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" DelegateFactory.setDelegate(",
" setOfInEachSubcomponentProvider,",
" SetFactory.<InEachSubcomponent>builder(0, 2)",
" .addCollectionProvider(super.contributionsInEachSubcomponent())",
" .addCollectionProvider(",
" AncestorModule_ProvideInAncestorFactory.create())",
" .build());",
" }",
"",
" @Override",
" public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
" return setOfInEachSubcomponentProvider;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void mapMultibindings_contributionsInLeaf() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<String, InLeaf> contributionsInLeaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"leafmodule\")",
" static InLeaf provideInLeaf() {",
" return new InLeaf();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<String, InLeaf> contributionsInLeaf() {",
" return ImmutableMap.<String, InLeaf>of(",
" \"leafmodule\",",
" LeafModule_ProvideInLeafFactory.proxyProvideInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
}
@Test
public void mapMultibindings_contributionsInAncestorOnly() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent",
"interface Leaf {",
" Map<String, InAncestor> contributionsInAncestor();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"ancestormodule\")",
" static InAncestor provideInAncestor() {",
" return new InAncestor();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Map<String, InAncestor> contributionsInAncestor() {",
" return ImmutableMap.<String, InAncestor>of(\"ancestormodule\",",
" AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void mapMultibindings_contributionsInLeafAndAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InEachSubcomponent");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"leafmodule\")",
" static InEachSubcomponent provideInLeaf() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
" return ImmutableMap.<String, InEachSubcomponent>of(",
" \"leafmodule\", LeafModule_ProvideInLeafFactory.proxyProvideInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"ancestormodule\")",
" static InEachSubcomponent provideInAncestor() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
" return ImmutableMap.<String, InEachSubcomponent>builderWithExpectedSize(2)",
" .put(\"ancestormodule\",",
" AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor())",
" .putAll(super.contributionsInEachSubcomponent())",
" .build();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void mapMultibindings_contributionsInLeafAndAncestor_frameworkInstance() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InEachSubcomponent");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Provider<Map<String, InEachSubcomponent>> contributionsInEachSubcomponent();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"leafmodule\")",
" static InEachSubcomponent provideInLeaf() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.MapFactory;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private Provider<Map<String, InEachSubcomponent>> ",
" mapOfStringAndInEachSubcomponentProvider;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.mapOfStringAndInEachSubcomponentProvider =",
" MapFactory.<String, InEachSubcomponent>builder(1)",
" .put(\"leafmodule\", LeafModule_ProvideInLeafFactory.create())",
" .build();",
" }",
"",
" @Override",
" public Provider<Map<String, InEachSubcomponent>> ",
" contributionsInEachSubcomponent() {",
" return mapOfStringAndInEachSubcomponentProvider;",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"ancestormodule\")",
" static InEachSubcomponent provideInAncestor() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.MapFactory;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Map<String, InEachSubcomponent>> ",
" mapOfStringAndInEachSubcomponentProvider = new DelegateFactory<>();",
"",
" protected LeafImpl() {}",
"",
" @Override",
" protected void configureInitialization() { ",
" super.configureInitialization();",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() { ",
" DelegateFactory.setDelegate(",
" mapOfStringAndInEachSubcomponentProvider,",
" MapFactory.<String, InEachSubcomponent>builder(2)",
" .putAll(super.contributionsInEachSubcomponent())",
" .put(",
" \"ancestormodule\",",
" AncestorModule_ProvideInAncestorFactory.create())",
" .build());",
" }",
"",
" @Override",
" public Provider<Map<String, InEachSubcomponent>> ",
" contributionsInEachSubcomponent() {",
" return mapOfStringAndInEachSubcomponentProvider;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void mapMultibindings_contributionsInLeafAndGrandAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InLeafAndGrandAncestor");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"leafmodule\")",
" static InLeafAndGrandAncestor provideInLeaf() {",
" return new InLeafAndGrandAncestor();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
" return ImmutableMap.<String, InLeafAndGrandAncestor>of(",
" \"leafmodule\", LeafModule_ProvideInLeafFactory.proxyProvideInLeaf());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.GrandAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = GrandAncestorModule.class)",
"interface GrandAncestor {",
" Ancestor ancestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.GrandAncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class GrandAncestorModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"grandancestormodule\")",
" static InLeafAndGrandAncestor provideInGrandAncestor() {",
" return new InLeafAndGrandAncestor();",
" }",
"}"));
JavaFileObject generatedGrandAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerGrandAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGrandAncestor implements GrandAncestor {",
" protected DaggerGrandAncestor() {}",
"",
" protected abstract class AncestorImpl extends DaggerAncestor {",
" protected AncestorImpl() {}",
"",
" protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
" protected LeafImpl() {}",
"",
" @Override",
" public Map<String, InLeafAndGrandAncestor>",
" contributionsInLeafAndGrandAncestor() {",
" return",
" ImmutableMap.<String, InLeafAndGrandAncestor>builderWithExpectedSize(2)",
" .put(\"grandancestormodule\",",
" GrandAncestorModule_ProvideInGrandAncestorFactory",
" .proxyProvideInGrandAncestor())",
" .putAll(super.contributionsInLeafAndGrandAncestor())",
" .build();",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGrandAncestor")
.hasSourceEquivalentTo(generatedGrandAncestor);
}
@Test
public void mapMultibindings_contributionsInLeafAndAncestorWithoutGuava() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InEachSubcomponent");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"leafmodule\")",
" static InEachSubcomponent provideInLeaf() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import java.util.Collections;",
"import java.util.Map",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
" return Collections.<String, InEachSubcomponent>singletonMap(",
" \"leafmodule\", LeafModule_ProvideInLeafFactory.proxyProvideInLeaf());",
" }",
"}");
Compilation compilation = compileWithoutGuava(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoMap;",
"import dagger.multibindings.StringKey;",
"import java.util.Map;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @StringKey(\"ancestormodule\")",
" static InEachSubcomponent provideInAncestor() {",
" return new InEachSubcomponent();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.MapBuilder;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
" return MapBuilder.<String, InEachSubcomponent>newMapBuilder(2)",
" .put(\"ancestormodule\",",
" AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor())",
" .putAll(super.contributionsInEachSubcomponent())",
" .build();",
" }",
" }",
"}");
compilation = compileWithoutGuava(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void mapMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(
filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<Integer, Multibound> instance();",
" MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntKey;",
"import dagger.multibindings.IntoMap;",
"import java.util.Map;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" @IntoMap",
" @IntKey(111)",
" static Multibound contribution() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<Integer, Multibound> instance() {",
" return ImmutableMap.<Integer, Multibound>of(",
" 111, LeafModule_ContributionFactory.proxyContribution());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.Multibinds;",
"import java.util.Map;",
"import javax.inject.Provider;",
"",
"@Module",
"interface AncestorModule {",
" @Provides",
" static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
" Provider<Map<Integer, Multibound>> frameworkInstance) {",
" return null;",
" }",
"",
" @Multibinds Map<Integer, Multibound> multibinds();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.MapFactory;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider;",
"",
" protected LeafImpl() {}",
"",
" protected void configureInitialization() { ",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() { ",
" this.mapOfIntegerAndMultiboundProvider =",
" MapFactory.<Integer, Multibound>builder(1)",
" .put(111, LeafModule_ContributionFactory.create())",
" .build();",
" }",
"",
" protected Provider getMapOfIntegerAndMultiboundProvider() {",
" return mapOfIntegerAndMultiboundProvider;",
" }",
"",
" @Override",
" public final MissingInLeaf_WillDependOnFrameworkInstance ",
" willDependOnFrameworkInstance() {",
" return AncestorModule_ProvidedInAncestorFactory.proxyProvidedInAncestor(",
" getMapOfIntegerAndMultiboundProvider());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void emptyMultibinds_set() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Multibound");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.Multibinds;",
"import java.util.Set;",
"",
"@Module",
"interface LeafModule {",
" @Multibinds",
" Set<Multibound> set();",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<Multibound> set();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<Multibound> set() {",
" return ImmutableSet.<Multibound>of();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoSet",
" static Multibound fromAncestor() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Set<Multibound> set() {",
" return ImmutableSet.<Multibound>of(",
" AncestorModule_FromAncestorFactory.proxyFromAncestor());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void emptyMultibinds_set_frameworkInstance() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Multibound");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.Multibinds;",
"import java.util.Set;",
"",
"@Module",
"interface LeafModule {",
" @Multibinds",
" Set<Multibound> set();",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Provider<Set<Multibound>> set();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Provider<Set<Multibound>> set() {",
" return SetFactory.<Multibound>empty();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoSet",
" static Multibound fromAncestor() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Set<Multibound>> setOfMultiboundProvider =",
" new DelegateFactory<>();",
"",
" protected LeafImpl() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" DelegateFactory.setDelegate(",
" setOfMultiboundProvider,",
" SetFactory.<Multibound>builder(1, 0)",
" .addProvider(AncestorModule_FromAncestorFactory.create())",
" .build());",
" }",
"",
" @Override",
" public Provider<Set<Multibound>> set() {",
" return setOfMultiboundProvider;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void emptyMultibinds_map() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Multibound");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.Multibinds;",
"import java.util.Map;",
"",
"@Module",
"interface LeafModule {",
" @Multibinds",
" Map<Integer, Multibound> map();",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Map<Integer, Multibound> map();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Map<Integer, Multibound> map() {",
" return ImmutableMap.<Integer, Multibound>of();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntKey;",
"import dagger.multibindings.IntoMap;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @IntKey(111)",
" static Multibound fromAncestor() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableMap;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public Map<Integer, Multibound> map() {",
" return ImmutableMap.<Integer, Multibound>of(",
" 111, AncestorModule_FromAncestorFactory.proxyFromAncestor());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void emptyMultibinds_map_frameworkInstance() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Multibound");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.Multibinds;",
"import java.util.Map;",
"",
"@Module",
"interface LeafModule {",
" @Multibinds",
" Map<Integer, Multibound> map();",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Map;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Provider<Map<Integer, Multibound>> map();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.MapFactory;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Provider<Map<Integer, Multibound>> map() {",
" return MapFactory.<Integer, Multibound>emptyMapProvider();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntKey;",
"import dagger.multibindings.IntoMap;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" @IntoMap",
" @IntKey(111)",
" static Multibound fromAncestor() {",
" return new Multibound();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.MapFactory;",
"import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider =",
" new DelegateFactory<>()",
"",
" protected LeafImpl() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" DelegateFactory.setDelegate(",
" mapOfIntegerAndMultiboundProvider,",
" MapFactory.<Integer, Multibound>builder(1)",
" .put(111, AncestorModule_FromAncestorFactory.create())",
" .build());",
" }",
"",
" @Override",
" public Provider<Map<Integer, Multibound>> map() {",
" return mapOfIntegerAndMultiboundProvider;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void provisionOverInjection_providedInAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.ProvidedInAncestor",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class ProvidedInAncestor {",
" @Inject",
" ProvidedInAncestor(String string) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" ProvidedInAncestor injectedInLeaf();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public ProvidedInAncestor injectedInLeaf() {",
" return new ProvidedInAncestor(getString());",
" }",
"",
" protected abstract String getString();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static ProvidedInAncestor provideProvidedInAncestor() {",
" return new ProvidedInAncestor(\"static\");",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public final ProvidedInAncestor injectedInLeaf() {",
" return AncestorModule_ProvideProvidedInAncestorFactory",
" .proxyProvideProvidedInAncestor();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void provisionOverInjection_providedInGrandAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.ProvidedInGrandAncestor",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class ProvidedInGrandAncestor {",
" @Inject",
" ProvidedInGrandAncestor(String string) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" ProvidedInGrandAncestor injectedInLeaf();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public ProvidedInGrandAncestor injectedInLeaf() {",
" return new ProvidedInGrandAncestor(getString());",
" }",
"",
" protected abstract String getString();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.GrandAncestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = GrandAncestorModule.class)",
"interface GrandAncestor {",
" Ancestor ancestor();",
"}"),
JavaFileObjects.forSourceLines(
"test.GrandAncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class GrandAncestorModule {",
" @Provides",
" static ProvidedInGrandAncestor provideProvidedInGrandAncestor() {",
" return new ProvidedInGrandAncestor(\"static\");",
" }",
"}"));
JavaFileObject generatedGrandAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerGrandAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerGrandAncestor implements GrandAncestor {",
" protected DaggerGrandAncestor() {}",
"",
" protected abstract class AncestorImpl extends DaggerAncestor {",
" protected AncestorImpl() {}",
"",
" protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
" protected LeafImpl() {}",
"",
" @Override",
" public final ProvidedInGrandAncestor injectedInLeaf() {",
" return GrandAncestorModule_ProvideProvidedInGrandAncestorFactory",
" .proxyProvideProvidedInGrandAncestor();",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGrandAncestor")
.hasSourceEquivalentTo(generatedGrandAncestor);
}
@Test
public void provisionOverInjection_indirectDependency() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.ProvidedInAncestor",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class ProvidedInAncestor {",
" @Inject",
" ProvidedInAncestor(String string) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.InjectedInLeaf",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class InjectedInLeaf {",
" @Inject",
" InjectedInLeaf(ProvidedInAncestor providedInAncestor) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" InjectedInLeaf injectedInLeaf();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public InjectedInLeaf injectedInLeaf() {",
" return InjectedInLeaf_Factory.newInjectedInLeaf(getProvidedInAncestor());",
" }",
"",
" protected abstract String getString();",
"",
" protected Object getProvidedInAncestor() {",
" return new ProvidedInAncestor(getString());",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static ProvidedInAncestor provideProvidedInAncestor() {",
" return new ProvidedInAncestor(\"static\");",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" protected final Object getProvidedInAncestor() {",
" return AncestorModule_ProvideProvidedInAncestorFactory",
" .proxyProvideProvidedInAncestor();",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void provisionOverInjection_prunedIndirectDependency() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "PrunedDependency");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.InjectsPrunedDependency",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class InjectsPrunedDependency {",
" @Inject",
" InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
"",
" private InjectsPrunedDependency() { }",
"",
" static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" InjectsPrunedDependency injectsPrunedDependency();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency_Factory.newInjectsPrunedDependency(",
" getPrunedDependency());",
" }",
"",
" protected abstract Object getPrunedDependency();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = RootModule.class)",
"interface Root {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.RootModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class RootModule {",
" @Provides",
" static InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency.create();",
" }",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
" public Builder rootModule(RootModule rootModule) {",
" Preconditions.checkNotNull(rootModule);",
" return this;",
" }",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {}",
"",
" @Override",
" protected Object getPrunedDependency() {",
" " + PRUNED_METHOD_BODY,
" }",
"",
" @Override",
" public InjectsPrunedDependency injectsPrunedDependency() {",
" return RootModule_InjectsPrunedDependencyFactory",
" .proxyInjectsPrunedDependency();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void provisionOverInjection_prunedDirectDependency_prunedInConcreteImplementation() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
// The binding for PrunedDependency will always exist, but will change from
// ModifiableBindingType.INJECTION to ModifiableBindingType.MISSING. We should correctly
// ignore this change leave the modifiable binding method alone
JavaFileObjects.forSourceLines(
"test.PrunedDependency",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class PrunedDependency {",
" @Inject PrunedDependency() {}",
"}"),
JavaFileObjects.forSourceLines(
"test.InjectsPrunedDependency",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class InjectsPrunedDependency {",
" @Inject",
" InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
"",
" private InjectsPrunedDependency() { }",
"",
" static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" InjectsPrunedDependency injectsPrunedDependency();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency_Factory.newInjectsPrunedDependency(",
" getPrunedDependency());",
" }",
"",
" protected Object getPrunedDependency() {",
" return new PrunedDependency();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = RootModule.class)",
"interface Root {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.RootModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class RootModule {",
" @Provides",
" static InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency.create();",
" }",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
" public Builder rootModule(RootModule rootModule) {",
" Preconditions.checkNotNull(rootModule);",
" return this;",
" }",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {}",
"",
" @Override",
" public InjectsPrunedDependency injectsPrunedDependency() {",
" return RootModule_InjectsPrunedDependencyFactory",
" .proxyInjectsPrunedDependency();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void provisionOverInjection_prunedDirectDependency_prunedInAbstractImplementation() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
// The binding for PrunedDependency will always exist, but will change from
// ModifiableBindingType.INJECTION to ModifiableBindingType.MISSING. We should correctly
// ignore this change leave the modifiable binding method alone
JavaFileObjects.forSourceLines(
"test.PrunedDependency",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class PrunedDependency {",
" @Inject PrunedDependency() {}",
"}"),
JavaFileObjects.forSourceLines(
"test.InjectsPrunedDependency",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class InjectsPrunedDependency {",
" @Inject",
" InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
"",
" private InjectsPrunedDependency() { }",
"",
" static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" InjectsPrunedDependency injectsPrunedDependency();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency_Factory.newInjectsPrunedDependency(",
" getPrunedDependency());",
" }",
"",
" protected Object getPrunedDependency() {",
" return new PrunedDependency();",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static InjectsPrunedDependency injectsPrunedDependency() {",
" return InjectsPrunedDependency.create();",
" }",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" public final InjectsPrunedDependency injectsPrunedDependency() {",
" return AncestorModule_InjectsPrunedDependencyFactory",
" .proxyInjectsPrunedDependency();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Ancestor ancestor();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Ancestor ancestor() {",
" return new AncestorImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class AncestorImpl extends DaggerAncestor {",
" private AncestorImpl() {}",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" private LeafImpl() {}",
// even though DaggerAncestor.LeafImpl.getPrunedDependency() was
// ModifiableBindingType.MISSING, it doesn't need to be reimplemented because there was
// a base implementation
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void productionSubcomponentAndModifiableFrameworkInstance() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Response", "ResponseDependency");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import com.google.common.util.concurrent.ListenableFuture;",
"import dagger.producers.ProductionSubcomponent;",
"import java.util.Set;",
"",
"@ProductionSubcomponent(modules = ResponseProducerModule.class)",
"interface Leaf {",
" ListenableFuture<Set<Response>> responses();",
"",
" @ProductionSubcomponent.Builder",
" interface Builder {",
" Leaf build();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.ResponseProducerModule",
"package test;",
"",
"import dagger.multibindings.IntoSet;",
"import dagger.producers.ProducerModule;",
"import dagger.producers.Produces;",
"",
"@ProducerModule",
"final class ResponseProducerModule {",
" @Produces",
" @IntoSet",
" static Response response(ResponseDependency responseDependency) {",
" return new Response();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.util.concurrent.ListenableFuture;",
"import dagger.producers.Producer;",
"import dagger.producers.internal.CancellationListener;",
"import dagger.producers.internal.Producers;",
"import dagger.producers.internal.SetProducer;",
"import dagger.producers.monitoring.ProductionComponentMonitor;",
"import java.util.Set;",
"import java.util.concurrent.Executor;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf, CancellationListener {",
" private Producer<Set<Response>> responsesEntryPoint;",
" private Producer<Response> responseProducer;",
" private Producer<Set<Response>> setOfResponseProducer;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.responseProducer =",
" ResponseProducerModule_ResponseFactory.create(",
" getProductionImplementationExecutorProvider(),",
" getProductionComponentMonitorProvider(),",
" getResponseDependencyProducer());",
" this.setOfResponseProducer =",
" SetProducer.<Response>builder(1, 0)",
" .addProducer(responseProducer).build();",
" this.responsesEntryPoint =",
" Producers.entryPointViewOf(getSetOfResponseProducer(), this);",
" }",
"",
" @Override",
" public ListenableFuture<Set<Response>> responses() {",
" return responsesEntryPoint.get();",
" }",
"",
" protected abstract Provider<Executor>",
" getProductionImplementationExecutorProvider();",
"",
" protected abstract Provider<ProductionComponentMonitor>",
" getProductionComponentMonitorProvider();",
"",
" protected abstract Producer getResponseDependencyProducer();",
"",
" protected Producer getSetOfResponseProducer() {",
" return setOfResponseProducer;",
" }",
"",
" @Override",
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
" Producers.cancel(getSetOfResponseProducer(), mayInterruptIfRunning);",
" Producers.cancel(responseProducer, mayInterruptIfRunning);",
" }",
"",
" public abstract static class Builder implements Leaf.Builder {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.ExecutorModule",
"package test;",
"",
"import com.google.common.util.concurrent.MoreExecutors;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.producers.Production;",
"import java.util.concurrent.Executor;",
"",
"@Module",
"final class ExecutorModule {",
" @Provides",
" @Production",
" static Executor executor() {",
" return MoreExecutors.directExecutor();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import com.google.common.util.concurrent.ListenableFuture;",
"import dagger.producers.ProductionComponent;",
"",
"@ProductionComponent(",
" modules = {",
" ExecutorModule.class,",
" ResponseDependencyProducerModule.class,",
" RootMultibindingModule.class,",
" })",
"interface Root {",
" Leaf.Builder leaf();",
"",
" @ProductionComponent.Builder",
" interface Builder {",
" Root build();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.ResponseDependencyProducerModule",
"package test;",
"",
"import com.google.common.util.concurrent.Futures;",
"import com.google.common.util.concurrent.ListenableFuture;",
"import dagger.producers.ProducerModule;",
"import dagger.producers.Produces;",
"",
"@ProducerModule",
"final class ResponseDependencyProducerModule {",
" @Produces",
" static ListenableFuture<ResponseDependency> responseDependency() {",
" return Futures.immediateFuture(new ResponseDependency());",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.RootMultibindingModule",
"package test;",
"",
"import dagger.multibindings.IntoSet;",
"import dagger.producers.ProducerModule;",
"import dagger.producers.Produces;",
"",
"@ProducerModule",
"final class RootMultibindingModule {",
" @Produces",
" @IntoSet",
" static Response response() {",
" return new Response();",
" }",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"import dagger.internal.DoubleCheck;",
"import dagger.internal.InstanceFactory;",
"import dagger.internal.SetFactory;",
"import dagger.producers.Producer;",
"import dagger.producers.internal.CancellationListener;",
"import dagger.producers.internal.DelegateProducer;",
"import dagger.producers.internal.Producers;",
"import dagger.producers.internal.SetProducer;",
"import dagger.producers.monitoring.ProductionComponentMonitor;",
"import java.util.Set;",
"import java.util.concurrent.Executor;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root, CancellationListener {",
" private Provider<Executor> productionImplementationExecutorProvider;",
" private Provider<Root> rootProvider;",
" private Provider<ProductionComponentMonitor> monitorProvider;",
" private Producer<ResponseDependency> responseDependencyProducer;",
" private Producer<Response> responseProducer;",
"",
" private DaggerRoot() {",
" initialize();",
" }",
"",
" public static Root.Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.productionImplementationExecutorProvider =",
" DoubleCheck.provider((Provider) ExecutorModule_ExecutorFactory.create());",
" this.rootProvider = InstanceFactory.create((Root) this);",
" this.monitorProvider =",
" DoubleCheck.provider(",
" Root_MonitoringModule_MonitorFactory.create(",
" rootProvider,",
" SetFactory.<ProductionComponentMonitor.Factory>empty()));",
" this.responseDependencyProducer =",
" ResponseDependencyProducerModule_ResponseDependencyFactory.create(",
" productionImplementationExecutorProvider, monitorProvider);",
" this.responseProducer =",
" RootMultibindingModule_ResponseFactory.create(",
" productionImplementationExecutorProvider, monitorProvider);",
" }",
"",
" @Override",
" public Leaf.Builder leaf() {",
" return new LeafBuilder();",
" }",
"",
" @Override",
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
" Producers.cancel(responseProducer, mayInterruptIfRunning);",
" Producers.cancel(responseDependencyProducer, mayInterruptIfRunning);",
" }",
"",
" private static final class Builder implements Root.Builder {",
" @Override",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" private final class LeafBuilder extends DaggerLeaf.Builder {",
" @Override",
" public Leaf build() {",
" return new LeafImpl();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf implements CancellationListener {",
" private Producer<Set<Response>> setOfResponseProducer = new DelegateProducer<>();",
"",
" private LeafImpl() {",
" configureInitialization();",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" DelegateProducer.setDelegate(",
" setOfResponseProducer,",
" SetProducer.<Response>builder(1, 1)",
" .addCollectionProducer(super.getSetOfResponseProducer())",
" .addProducer(DaggerRoot.this.responseProducer)",
" .build());",
" }",
"",
" @Override",
" protected Provider<Executor> getProductionImplementationExecutorProvider() {",
" return DaggerRoot.this.productionImplementationExecutorProvider;",
" }",
"",
" @Override",
" protected Provider<ProductionComponentMonitor>",
" getProductionComponentMonitorProvider() {",
" return DaggerRoot.this.monitorProvider;",
" }",
"",
" @Override",
" protected Producer getResponseDependencyProducer() {",
" return DaggerRoot.this.responseDependencyProducer;",
" }",
"",
" @Override",
" protected Producer getSetOfResponseProducer() {",
" return setOfResponseProducer;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void lazyOfModifiableBinding() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Lazy;",
"import dagger.Subcomponent;",
"import javax.inject.Provider;",
"",
"@Subcomponent",
"interface Leaf {",
" Lazy<MissingInLeaf> lazy();",
" Provider<Lazy<MissingInLeaf>> providerOfLazy();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.Lazy;",
"import dagger.internal.DoubleCheck;",
"import dagger.internal.ProviderOfLazy;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Lazy<MissingInLeaf> lazy() {",
" return DoubleCheck.lazy(getMissingInLeafProvider());",
" }",
"",
" @Override",
" public Provider<Lazy<MissingInLeaf>> providerOfLazy() {",
" return ProviderOfLazy.create(getMissingInLeafProvider());",
" }",
"",
" protected abstract Provider getMissingInLeafProvider();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class AncestorModule {",
" @Provides",
" static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" @Override",
" protected final Provider getMissingInLeafProvider() {",
" return AncestorModule_SatisfiedInAncestorFactory.create();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void missingBindingAccessInLeafAndAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(
filesToCompile, "Missing", "DependsOnMissing", "ProvidedInAncestor_InducesSetBinding");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.IntoSet;",
"import dagger.Provides;",
"import javax.inject.Provider;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" static DependsOnMissing test(",
" Missing missing,",
" Provider<Missing> missingProvider,",
" ProvidedInAncestor_InducesSetBinding missingInLeaf) {",
" return new DependsOnMissing();",
" }",
"",
" @Provides",
" @IntoSet",
" static Object unresolvedSetBinding(",
" Missing missing, Provider<Missing> missingProvider) {",
" return new Object();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" DependsOnMissing instance();",
" Provider<DependsOnMissing> frameworkInstance();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private Provider<DependsOnMissing> testProvider;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.testProvider =",
" LeafModule_TestFactory.create(",
" getMissingProvider(), getProvidedInAncestor_InducesSetBindingProvider());",
" }",
"",
" @Override",
" public DependsOnMissing instance() {",
" return LeafModule_TestFactory.proxyTest(",
" getMissing(),",
" getMissingProvider(),",
" getProvidedInAncestor_InducesSetBinding());",
" }",
"",
" @Override",
" public Provider<DependsOnMissing> frameworkInstance() {",
" return testProvider;",
" }",
"",
" protected abstract Object getMissing();",
" protected abstract Provider getMissingProvider();",
" protected abstract Object getProvidedInAncestor_InducesSetBinding();",
" protected abstract Provider getProvidedInAncestor_InducesSetBindingProvider();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.IntoSet;",
"import dagger.Provides;",
"import java.util.Set;",
"",
"@Module",
"interface AncestorModule {",
" @Provides",
" static ProvidedInAncestor_InducesSetBinding providedInAncestor(",
" Set<Object> setThatInducesMissingBindingInChildSubclassImplementation) {",
" return new ProvidedInAncestor_InducesSetBinding();",
" }",
"",
" @Provides",
" @IntoSet",
" static Object setContribution() {",
" return new Object();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.SetFactory;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private Provider<Object> unresolvedSetBindingProvider;",
" private Provider<Set<Object>> setOfObjectProvider;",
" private Provider<ProvidedInAncestor_InducesSetBinding> ",
" providedInAncestorProvider = ",
" new DelegateFactory<>();",
"",
" protected LeafImpl() {}",
"",
" @Override",
" protected void configureInitialization() {",
" super.configureInitialization();",
" initialize();",
" }",
"",
" private Object getUnresolvedSetBinding() {",
" return LeafModule_UnresolvedSetBindingFactory.proxyUnresolvedSetBinding(",
" getMissing(), getMissingProvider());",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.unresolvedSetBindingProvider =",
" LeafModule_UnresolvedSetBindingFactory.create(getMissingProvider());",
" this.setOfObjectProvider =",
" SetFactory.<Object>builder(2, 0)",
" .addProvider(AncestorModule_SetContributionFactory.create())",
" .addProvider(unresolvedSetBindingProvider)",
" .build();",
" DelegateFactory.setDelegate(",
" providedInAncestorProvider,",
" AncestorModule_ProvidedInAncestorFactory.create(getSetOfObjectProvider()));",
" }",
"",
" protected Set<Object> getSetOfObject() {",
" return ImmutableSet.<Object>of(",
" AncestorModule_SetContributionFactory.proxySetContribution(),",
" getUnresolvedSetBinding());",
" }",
"",
" @Override",
" protected final Object getProvidedInAncestor_InducesSetBinding() {",
" return AncestorModule_ProvidedInAncestorFactory.proxyProvidedInAncestor(",
" getSetOfObject());",
" }",
"",
" protected Provider<Set<Object>> getSetOfObjectProvider() {",
" return setOfObjectProvider;",
" }",
"",
" @Override",
" protected final Provider getProvidedInAncestor_InducesSetBindingProvider() {",
" return providedInAncestorProvider;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void subcomponentBuilders() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "InducesDependenciesOnBuilderFields");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class LeafModule {",
" private final Object object;",
"",
" LeafModule(Object object) {",
" this.object = object;",
" }",
"",
" @Provides",
" Object fromModule() {",
" return object;",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.MultibindingsModule",
"package test;",
"",
"import dagger.Binds;",
"import dagger.Module;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"interface MultibindingsModule {",
" @Binds",
" @IntoSet",
" String string(String string);",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.BindsInstance;",
"import dagger.Subcomponent;",
"import javax.inject.Provider;",
"",
"@Subcomponent(modules = {LeafModule.class, MultibindingsModule.class})",
"interface Leaf {",
" int bindsInstance();",
" Object fromModule();",
" InducesDependenciesOnBuilderFields inducesDependenciesOnBuilderFields();",
"",
" @Subcomponent.Builder",
" interface Builder {",
" @BindsInstance Builder bindsInstance(int boundInstance);",
" @BindsInstance Builder inducedInSubclass(String induced);",
" Builder module(LeafModule module);",
"",
" Leaf build();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private Integer bindsInstance;",
" private LeafModule leafModule;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization(",
" LeafModule leafModuleParam, Integer bindsInstanceParam) {",
" this.bindsInstance = bindsInstanceParam;",
" this.leafModule = leafModuleParam;",
" }",
"",
" @Override",
" public int bindsInstance() {",
" return bindsInstance;",
" }",
"",
" @Override",
" public Object fromModule() {",
" return LeafModule_FromModuleFactory.proxyFromModule(leafModule());",
" }",
"",
" protected LeafModule leafModule() {",
" return leafModule;",
" }",
"",
" public abstract static class Builder implements Leaf.Builder {",
" protected LeafModule leafModule;",
" protected Integer bindsInstance;",
" protected String inducedInSubclass;",
"",
" @Override",
" public Builder bindsInstance(int boundInstance) {",
" this.bindsInstance = Preconditions.checkNotNull(boundInstance);",
" return this;",
" }",
"",
" @Override",
" public Builder inducedInSubclass(String induced) {",
" this.inducedInSubclass = Preconditions.checkNotNull(induced);",
" return this;",
" }",
"",
" @Override",
" public Builder module(LeafModule module) {",
" this.leafModule = Preconditions.checkNotNull(module);",
" return this;",
" }",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = MultibindingInducingModule.class)",
"interface Ancestor {",
" Leaf.Builder leaf();",
"}"),
JavaFileObjects.forSourceLines(
"test.MultibindingInducingModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.multibindings.Multibinds;",
"import dagger.Provides;",
"import java.util.Set;",
"",
"@Module",
"interface MultibindingInducingModule {",
" @Provides",
" static InducesDependenciesOnBuilderFields induce(",
" Set<String> multibindingWithBuilderFieldDeps) { ",
" return new InducesDependenciesOnBuilderFields();",
" }",
"",
" @Multibinds",
" Set<String> multibinding();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private String inducedInSubclass;",
"",
" protected LeafImpl() {}",
"",
" protected void configureInitialization(",
" LeafModule leafModule,",
" Integer bindsInstance,",
" String inducedInSubclassParam) {",
" this.inducedInSubclass = inducedInSubclassParam;",
" configureInitialization(leafModule, bindsInstance);",
" }",
"",
" protected Set<String> getSetOfString() {",
" return ImmutableSet.<String>of(inducedInSubclass);",
" }",
"",
" @Override",
" public final InducesDependenciesOnBuilderFields",
" inducesDependenciesOnBuilderFields() {",
" return MultibindingInducingModule_InduceFactory.proxyInduce(getSetOfString());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Ancestor ancestor();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Ancestor ancestor() {",
" return new AncestorImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class AncestorImpl extends DaggerAncestor {",
" private AncestorImpl() {}",
"",
" @Override",
" public Leaf.Builder leaf() {",
" return new LeafBuilder();",
" }",
"",
" private final class LeafBuilder extends DaggerLeaf.Builder {",
" @Override",
" public Leaf build() {",
// TODO(b/117833324): Can we stick the validations into a method on the base class
// builder so that the contents of this method are just call to that and then new
// FooImpl? But repeated modules may make this more complicated, since those *should*
// be null
" Preconditions.checkBuilderRequirement(leafModule, LeafModule.class);",
" Preconditions.checkBuilderRequirement(bindsInstance, Integer.class);",
" Preconditions.checkBuilderRequirement(inducedInSubclass, String.class);",
" return new LeafImpl(leafModule, bindsInstance, inducedInSubclass);",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" private LeafModule leafModule;",
"",
" private LeafImpl(",
" LeafModule leafModuleParam,",
" Integer bindsInstance,",
" String inducedInSubclass) {",
" this.leafModule = leafModuleParam;",
" configureInitialization(leafModuleParam, bindsInstance, inducedInSubclass);",
" }",
"",
" @Override",
" protected LeafModule leafModule() {",
" return leafModule;",
" }",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void subcomponentBuilders_moduleWithUnusedInstanceBindings() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Used", "Unused");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.ModuleWithUsedBinding",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class ModuleWithUsedBinding {",
" @Provides",
" Used used() {",
" return new Used();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.ModuleWithUnusedBinding",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class ModuleWithUnusedBinding {",
" @Provides",
" Unused unused() {",
" return new Unused();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = {ModuleWithUsedBinding.class, ModuleWithUnusedBinding.class})",
"interface Leaf {",
" Used used();",
"",
" @Subcomponent.Builder",
" interface Builder {",
" Leaf build();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private ModuleWithUsedBinding moduleWithUsedBinding;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization(",
" ModuleWithUsedBinding moduleWithUsedBindingParam) {",
" this.moduleWithUsedBinding = moduleWithUsedBindingParam;",
" }",
"",
" @Override",
" public Used used() {",
" return ModuleWithUsedBinding_UsedFactory.proxyUsed(",
" moduleWithUsedBinding());",
" }",
"",
" protected ModuleWithUsedBinding moduleWithUsedBinding() {",
" return moduleWithUsedBinding;",
" }",
"",
" public abstract static class Builder implements Leaf.Builder {",
" protected ModuleWithUsedBinding moduleWithUsedBinding;",
" protected ModuleWithUnusedBinding moduleWithUnusedBinding;",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" Leaf.Builder leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf.Builder leaf() {",
" return new LeafBuilder();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" private final class LeafBuilder extends DaggerLeaf.Builder {",
" @Override",
" public Leaf build() {",
" if (moduleWithUsedBinding == null) {",
" this.moduleWithUsedBinding = new ModuleWithUsedBinding();",
" }",
// ModuleWithUnusedBinding is not verified since it's not used
" return new LeafImpl(moduleWithUsedBinding);",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private ModuleWithUsedBinding moduleWithUsedBinding;",
"",
" private LeafImpl(ModuleWithUsedBinding moduleWithUsedBindingParam) {",
" this.moduleWithUsedBinding = moduleWithUsedBindingParam;",
" configureInitialization(moduleWithUsedBindingParam);",
" }",
"",
" @Override",
" protected ModuleWithUsedBinding moduleWithUsedBinding() {",
" return moduleWithUsedBinding;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void subcomponentBuilders_repeatedModule() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.RepeatedModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class RepeatedModule {",
" @Provides",
" int i() {",
" return 1;",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = RepeatedModule.class)",
"interface Leaf {",
" int i();",
"",
" @Subcomponent.Builder",
" interface Builder {",
" Builder repeatedModule(RepeatedModule repeatedModule);",
" Leaf build();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private RepeatedModule repeatedModule;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization(RepeatedModule repeatedModuleParam) {",
" this.repeatedModule = repeatedModuleParam;",
" }",
"",
" @Override",
" public int i() {",
" return repeatedModule().i();",
" }",
"",
" protected RepeatedModule repeatedModule() {",
" return repeatedModule;",
" }",
"",
" public abstract static class Builder implements Leaf.Builder {",
" protected RepeatedModule repeatedModule;",
"",
" @Override",
" public Builder repeatedModule(RepeatedModule repeatedModule) {",
" this.repeatedModule = Preconditions.checkNotNull(repeatedModule);",
" return this;",
" }",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = RepeatedModule.class)",
"interface Root {",
" Leaf.Builder leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.Preconditions;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private RepeatedModule repeatedModule;",
"",
" private DaggerRoot(RepeatedModule repeatedModuleParam) {",
" this.repeatedModule = repeatedModuleParam;",
" }",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf.Builder leaf() {",
" return new LeafBuilder();",
" }",
"",
" public static final class Builder {",
" private RepeatedModule repeatedModule;",
"",
" private Builder() {}",
"",
" public Builder repeatedModule(RepeatedModule repeatedModule) {",
" this.repeatedModule = Preconditions.checkNotNull(repeatedModule);",
" return this;",
" }",
"",
" public Root build() {",
" if (repeatedModule == null) {",
" this.repeatedModule = new RepeatedModule();",
" }",
" return new DaggerRoot(repeatedModule);",
" }",
" }",
"",
" private final class LeafBuilder extends DaggerLeaf.Builder {",
" @Override",
" public LeafBuilder repeatedModule(RepeatedModule repeatedModule) {",
" throw new UnsupportedOperationException(",
" String.format(",
" \"%s cannot be set because it is inherited from the enclosing component\",",
" RepeatedModule.class.getCanonicalName()));",
" }",
"",
" @Override",
" public Leaf build() {",
" return new LeafImpl();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {",
" configureInitialization(null);",
" }",
"",
" @Override",
" protected RepeatedModule repeatedModule() {",
" return DaggerRoot.this.repeatedModule;",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void bindsWithMissingDependency() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Binds;",
"",
"@Module",
"interface LeafModule {",
" @Binds Object missingBindsDependency(MissingInLeaf missing);",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Object bindsWithMissingDependencyInLeaf();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.MissingInLeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"interface MissingInLeafModule {",
" @Provides",
" static MissingInLeaf boundInRoot() {",
" return new MissingInLeaf();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = MissingInLeafModule.class)",
"interface Root {",
" Leaf leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {}",
"",
" @Override",
" public Object bindsWithMissingDependencyInLeaf() {",
" return MissingInLeafModule_BoundInRootFactory.proxyBoundInRoot();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void bindsWithMissingDependency_pruned() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "MissingInLeaf");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Binds;",
"",
"@Module",
"interface LeafModule {",
" @Binds Object missingBindsDependency(MissingInLeaf missing);",
"}"),
JavaFileObjects.forSourceLines(
"test.DependsOnBindsWithMissingDep",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class DependsOnBindsWithMissingDep {",
" @Inject DependsOnBindsWithMissingDep(Object bindsWithMissingDep) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep() {",
" return new DependsOnBindsWithMissingDep(getObject());",
" }",
"",
" protected abstract Object getObject();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.PrunesInjectConstructorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"interface PrunesInjectConstructorModule {",
" @Provides",
" static DependsOnBindsWithMissingDep pruneInjectConstructor() {",
" return new DependsOnBindsWithMissingDep(new Object());",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = PrunesInjectConstructorModule.class)",
"interface Root {",
" Leaf leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {}",
"",
" @Override",
" protected Object getObject() {",
" " + PRUNED_METHOD_BODY,
" }",
"",
" @Override",
" public DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep() {",
" return PrunesInjectConstructorModule_PruneInjectConstructorFactory",
" .proxyPruneInjectConstructor();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void modifiedProducerFromProvider() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "DependsOnModifiedProducerFromProvider");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.multibindings.IntoSet;",
"import dagger.producers.ProducerModule;",
"import dagger.producers.Produces;",
"import dagger.Provides;",
"import java.util.Set;",
"",
"@ProducerModule",
"interface LeafModule {",
" @Produces",
" static DependsOnModifiedProducerFromProvider dependsOnModified(Set<String> set) {",
" return new DependsOnModifiedProducerFromProvider();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.producers.Producer;",
"import dagger.producers.ProductionSubcomponent;",
"import java.util.Set;",
"",
"@ProductionSubcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Producer<DependsOnModifiedProducerFromProvider>",
" dependsOnModifiedProducerFromProvider();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.producers.Producer;",
"import dagger.producers.internal.CancellationListener;",
"import dagger.producers.internal.Producers;",
"import dagger.producers.monitoring.ProductionComponentMonitor;",
"import java.util.Set;",
"import java.util.concurrent.Executor;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf, CancellationListener {",
" private Producer<DependsOnModifiedProducerFromProvider>",
" dependsOnModifiedProducerFromProviderEntryPoint;",
" private Producer<DependsOnModifiedProducerFromProvider> dependsOnModifiedProducer;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.dependsOnModifiedProducer =",
" LeafModule_DependsOnModifiedFactory.create(",
" getProductionImplementationExecutorProvider(),",
" getProductionComponentMonitorProvider(),",
" getSetOfStringProducer());",
" this.dependsOnModifiedProducerFromProviderEntryPoint =",
" Producers.entryPointViewOf(dependsOnModifiedProducer, this);",
" }",
"",
" @Override",
" public Producer<DependsOnModifiedProducerFromProvider> ",
" dependsOnModifiedProducerFromProvider() {",
" return dependsOnModifiedProducerFromProviderEntryPoint;",
" }",
"",
" protected abstract Provider<Executor> ",
" getProductionImplementationExecutorProvider();",
"",
" protected abstract Provider<ProductionComponentMonitor>",
" getProductionComponentMonitorProvider();",
"",
" protected abstract Producer<Set<String>> getSetOfStringProducer();",
"",
" @Override",
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
" Producers.cancel(dependsOnModifiedProducer, mayInterruptIfRunning);",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.RootModule",
"package test;",
"",
"import dagger.multibindings.IntoSet;",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.producers.Production;",
"import java.util.Set;",
"import java.util.concurrent.Executor;",
"",
"@Module",
"interface RootModule {",
" @Provides",
" @IntoSet",
" static String induceModificationInLeaf() {",
" return new String();",
" }",
"",
" @Provides",
" @Production",
" static Executor productionExecutor() {",
" return null;",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = RootModule.class)",
"interface Root {",
" Leaf leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
"import dagger.internal.DoubleCheck;",
"import dagger.internal.InstanceFactory;",
"import dagger.internal.SetFactory;",
"import dagger.producers.Producer;",
"import dagger.producers.internal.CancellationListener;",
"import dagger.producers.internal.DelegateProducer;",
"import dagger.producers.internal.Producers;",
"import dagger.producers.monitoring.ProductionComponentMonitor;",
"import java.util.Set;",
"import java.util.concurrent.Executor;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
" return new Builder();",
" }",
"",
" public static Root create() {",
" return new Builder().build();",
" }",
"",
" @Override",
" public Leaf leaf() {",
" return new LeafImpl();",
" }",
"",
" public static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
" return new DaggerRoot();",
" }",
" }",
"",
" protected final class LeafImpl extends DaggerLeaf implements CancellationListener {",
" private Provider<Executor> productionImplementationExecutorProvider =",
" new DelegateFactory<>();",
" private Provider<Leaf> leafProvider;",
" private Provider<ProductionComponentMonitor> monitorProvider =",
" new DelegateFactory<>();",
" private Provider<Set<String>> setOfStringProvider;",
" private Producer<Set<String>> setOfStringProducer = new DelegateProducer<>();",
"",
" private LeafImpl() {",
" configureInitialization();",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" DelegateFactory.setDelegate(",
" productionImplementationExecutorProvider,",
" DoubleCheck.provider(",
" (Provider) RootModule_ProductionExecutorFactory.create()));",
" this.leafProvider = InstanceFactory.create((Leaf) this);",
" DelegateFactory.setDelegate(",
" monitorProvider,",
" DoubleCheck.provider(",
" Leaf_MonitoringModule_MonitorFactory.create(",
" leafProvider, getSetOfFactoryProvider())));",
" this.setOfStringProvider =",
" SetFactory.<String>builder(1, 0)",
" .addProvider(RootModule_InduceModificationInLeafFactory.create())",
" .build();",
" DelegateProducer.setDelegate(",
" setOfStringProducer,",
" Producers.producerFromProvider(getSetOfStringProvider()));",
" }",
"",
" @Override",
" protected Provider<Executor> getProductionImplementationExecutorProvider() {",
" return productionImplementationExecutorProvider;",
" }",
"",
" protected Provider<Set<ProductionComponentMonitor.Factory>> ",
" getSetOfFactoryProvider() {",
" return SetFactory.<ProductionComponentMonitor.Factory>empty();",
" }",
"",
" @Override",
" protected Provider<ProductionComponentMonitor> ",
" getProductionComponentMonitorProvider() {",
" return monitorProvider;",
" }",
"",
" protected Provider<Set<String>> getSetOfStringProvider() {",
" return setOfStringProvider;",
" }",
"",
" @Override",
" protected Producer<Set<String>> getSetOfStringProducer() {",
" return setOfStringProducer;",
" }",
"",
" @Override",
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
" super.onProducerFutureCancelled(mayInterruptIfRunning);",
" Producers.cancel(getSetOfStringProducer(), mayInterruptIfRunning);",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.hasSourceEquivalentTo(generatedRoot);
}
@Test
public void bindsMissingDep_Multibindings() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Binds;",
"import dagger.Module;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"interface LeafModule {",
" @Binds",
" @IntoSet",
" CharSequence bindsMultibindingWithMissingDep(String string);",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import java.util.Set;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Set<CharSequence> set();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Set<CharSequence> set() {",
" return ImmutableSet.<CharSequence>of(getBindsMultibindingWithMissingDep());",
" }",
"",
// The expected output here is subtle: the Key of
// LeafModule.bindsMultibindingWithMissingDep() is Set<CharSequence>, but the binding
// method should only be returning an individual CharSequence. Otherwise the
// ImmutableSet factory method above will fail.
" protected abstract CharSequence getBindsMultibindingWithMissingDep();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
}
@Test
public void modifiableBindingMethods_namesDedupedAcrossImplementations() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"foo.Thing",
"package foo;",
"", // force multi-line format
"public interface Thing extends CharSequence {}"),
JavaFileObjects.forSourceLines(
"bar.Thing",
"package bar;",
"", // force multi-line format
"public interface Thing extends Runnable {}"),
JavaFileObjects.forSourceLines(
"test.WillInduceSetOfRunnable",
"package test;",
"", // force multi-line format
"class WillInduceSetOfRunnable {}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module",
"interface LeafModule {",
" @Provides",
" static CharSequence depOnFooThing(foo.Thing thing) {",
" return thing.toString();",
" }",
"",
" @Provides",
" @IntoSet",
" static Runnable depOnBarThing(bar.Thing thing) {",
" return () -> {};",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" CharSequence inducesFoo();",
" WillInduceSetOfRunnable willInduceSetOfRunnable();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import foo.Thing;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public CharSequence inducesFoo() {",
" return LeafModule_DepOnFooThingFactory.proxyDepOnFooThing(getThing());",
" }",
"",
" protected abstract Thing getThing();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.Multibinds;",
"import java.util.Set;",
"",
"@Module",
"interface AncestorModule {",
" @Provides",
" static WillInduceSetOfRunnable induce(Set<Runnable> set) {",
" return null;",
" }",
"",
" @Multibinds Set<Runnable> runnables();",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" Leaf leaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import bar.Thing;",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
"",
" private Runnable getDepOnBarThing() {",
" return LeafModule_DepOnBarThingFactory.proxyDepOnBarThing(getThing2());",
" }",
"",
" protected abstract Thing getThing2();",
"",
" protected Set<Runnable> getSetOfRunnable() {",
" return ImmutableSet.<Runnable>of(getDepOnBarThing());",
" }",
"",
" @Override",
" public final WillInduceSetOfRunnable willInduceSetOfRunnable() {",
" return AncestorModule_InduceFactory.proxyInduce(getSetOfRunnable());",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
/**
* This test verifies that Dagger can find the appropriate child subcomponent
* super-implementation, even if it is not enclosed in the current component's
* super-implementation. This can happen if a subcomponent is installed with a module's {@code
* subcomponents} attribute, but the binding is not accessed in a super-implementation. To exhibit
* this, we use multibindings that reference the pruned subcomponent, but make the multibinding
* also unresolved in the base implementation. An ancestor component defines a binding that
* depends on the multibinding, which induces the previously unresolved multibinding
* contributions, which itself induces the previously unresolved subcomponent.
*/
@Test
public void subcomponentInducedFromAncestor() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Inducer");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.InducedSubcomponent",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface InducedSubcomponent {",
" @Subcomponent.Builder",
" interface Builder {",
" InducedSubcomponent build();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.MaybeLeaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = InducedSubcomponentModule.class)",
"interface MaybeLeaf {",
" Inducer inducer();",
"}"),
JavaFileObjects.forSourceLines(
"test.MaybeLeaf",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.IntoSet;",
"",
"@Module(subcomponents = InducedSubcomponent.class)",
"interface InducedSubcomponentModule {",
" @Provides",
" @IntoSet",
" static Object inducedSet(InducedSubcomponent.Builder builder) {",
" return new Object();",
" }",
"}"));
JavaFileObject generatedMaybeLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerMaybeLeaf implements MaybeLeaf {",
" protected DaggerMaybeLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerMaybeLeaf")
.hasSourceEquivalentTo(generatedMaybeLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.AncestorModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import dagger.multibindings.Multibinds;",
"import java.util.Set;",
"",
"@Module",
"interface AncestorModule {",
" @Provides",
" static Inducer inducer(Set<Object> set) {",
" return null;",
" }",
"",
" @Multibinds Set<Object> set();",
"}"),
JavaFileObjects.forSourceLines(
"test.Ancestor",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = AncestorModule.class)",
"interface Ancestor {",
" MaybeLeaf noLongerLeaf();",
"}"));
JavaFileObject generatedAncestor =
JavaFileObjects.forSourceLines(
"test.DaggerAncestor",
"package test;",
"",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
" protected abstract class MaybeLeafImpl extends DaggerMaybeLeaf {",
" protected MaybeLeafImpl() {}",
"",
" private Object getInducedSet() {",
" return InducedSubcomponentModule_InducedSetFactory.proxyInducedSet(",
" getInducedSubcomponentBuilder());",
" }",
"",
" protected abstract Object getInducedSubcomponentBuilder();",
"",
" protected Set<Object> getSetOfObject() {",
" return ImmutableSet.<Object>of(getInducedSet());",
" }",
"",
" @Override",
" public final Inducer inducer() {",
" return AncestorModule_InducerFactory.proxyInducer(getSetOfObject());",
" }",
"",
" protected abstract class InducedSubcomponentImpl extends",
" DaggerInducedSubcomponent {",
// ^ Note that this is DaggerInducedSubcomponent, not
// DaggerMaybeLeaf.InducedSubcomponentImpl
" protected InducedSubcomponentImpl() {}",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
.hasSourceEquivalentTo(generatedAncestor);
}
@Test
public void rootScopedAtInjectConstructor_effectivelyMissingInSubcomponent() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "ProvidesMethodRootScoped");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.RootScope",
"package test;",
"",
"import javax.inject.Scope;",
"",
"@Scope",
"public @interface RootScope {}"),
JavaFileObjects.forSourceLines(
"test.AtInjectRootScoped",
"package test;",
"",
"import javax.inject.Inject;",
"",
"@RootScope",
"class AtInjectRootScoped {",
" @Inject AtInjectRootScoped() {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent",
"interface Leaf {",
" AtInjectRootScoped shouldBeEffectivelyMissingInLeaf();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Component;",
"",
"@RootScope",
"@Component",
"interface Root {",
" Leaf leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" protected final class LeafImpl extends DaggerLeaf {",
" @Override",
" public AtInjectRootScoped shouldBeEffectivelyMissingInLeaf() {",
" return DaggerRoot.this.atInjectRootScopedProvider.get();",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.containsElementsIn(generatedRoot);
}
@Test
public void prunedModuleWithInstanceState() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
createAncillaryClasses(filesToCompile, "Pruned");
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Modified",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class Modified {",
" @Inject Modified(Pruned pruned) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.LeafModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class LeafModule {",
" @Provides",
" Pruned pruned() {",
" return new Pruned();",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"@Subcomponent(modules = LeafModule.class)",
"interface Leaf {",
" Modified modified();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
"",
" @Override",
" public Modified modified() {",
" return new Modified(LeafModule_PrunedFactory.proxyPruned(leafModule()));",
" }",
"",
" protected abstract LeafModule leafModule();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.RootModule",
"package test;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"",
"@Module",
"class RootModule {",
" @Provides",
" static Modified modified() {",
" return new Modified(null);",
" }",
"}"),
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component(modules = RootModule.class)",
"interface Root {",
" Leaf leaf();",
"}"));
String exceptionText =
" has been pruned from the final resolved binding graph. If this exception is thrown, it "
+ "is a Dagger bug, so please report it!";
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerRoot",
"package test;",
"",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" protected final class LeafImpl extends DaggerLeaf {",
" @Override",
" public Modified modified() {",
" return RootModule_ModifiedFactory.proxyModified();",
" }",
"",
" @Override",
" protected LeafModule leafModule() {",
" throw new UnsupportedOperationException(",
" LeafModule.class + \"" + exceptionText + "\");",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.containsElementsIn(generatedRoot);
}
@Test
public void modifiableCycles() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.A",
"package test;",
"",
"import javax.inject.Inject;",
"",
"class A {",
" @Inject A(B b) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.B",
"package test;",
"",
"import javax.inject.Inject;",
"import javax.inject.Provider;",
"",
"class B {",
" @Inject B(Provider<A> a) {}",
"}"),
JavaFileObjects.forSourceLines(
"test.Leaf",
"package test;",
"",
"import dagger.Subcomponent;",
"",
"import javax.inject.Provider;",
"",
"@Subcomponent",
"interface Leaf {",
" Provider<A> frameworkInstanceCycle();",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import dagger.internal.DelegateFactory;",
IMPORT_GENERATED_ANNOTATION,
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" private Provider<A> aProvider;",
" private Provider<B> bProvider;",
"",
" protected DaggerLeaf() {}",
"",
" protected void configureInitialization() {",
" initialize();",
" }",
"",
" @SuppressWarnings(\"unchecked\")",
" private void initialize() {",
" this.aProvider = new DelegateFactory<>();",
" this.bProvider = B_Factory.create(frameworkInstanceCycle());",
" DelegateFactory.setDelegate(aProvider, A_Factory.create(getBProvider()));",
" }",
"",
" @Override",
" public Provider<A> frameworkInstanceCycle() {",
" return aProvider;",
" }",
"",
" protected Provider getBProvider() {",
" return bProvider;",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
.hasSourceEquivalentTo(generatedLeaf);
}
/**
* This tests a regression case where the component builder in the base implementation used one
* set of disambiguated names from all of the {@link
* BindingGraph#possiblyNecessaryRequirements()}, and the final implementation used a different
* set of disambiguated names from the resolved {@link BindingGraph#componentRequirements()}. This
* resulted in generated output that didn't compile, as the builder implementation attempted to
* use the new names in validation, which didn't line up with the old names.
*/
@Test
public void componentBuilderFields_consistencyAcrossImplementations() {
ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
filesToCompile.add(
JavaFileObjects.forSourceLines(
"a.Mod",
"package a;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import javax.inject.Named;",
"",
"@Module",
"public class Mod {",
" @Provides",
" @Named(\"a\")",
" int i() { return 0; }",
"}"),
JavaFileObjects.forSourceLines(
"b.Mod",
"package b;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import javax.inject.Named;",
"",
"@Module",
"public class Mod {",
" @Provides",
" @Named(\"b\")",
" int i() { return 0; }",
"}"),
JavaFileObjects.forSourceLines(
"c.Mod",
"package c;",
"",
"import dagger.Module;",
"import dagger.Provides;",
"import javax.inject.Named;",
"",
"@Module",
"public class Mod {",
" @Provides",
" @Named(\"c\")",
" int i() { return 0; }",
"}"),
JavaFileObjects.forSourceLines(
"test.HasUnusedModuleLeaf",
"package test;",
"",
"import dagger.Subcomponent;",
"import javax.inject.Named;",
"",
"@Subcomponent(modules = {a.Mod.class, b.Mod.class, c.Mod.class})",
"interface HasUnusedModuleLeaf {",
" @Named(\"a\") int a();",
// b omitted intentionally
" @Named(\"c\") int c();",
"",
" @Subcomponent.Builder",
" interface Builder {",
" HasUnusedModuleLeaf build();",
" }",
"}"));
JavaFileObject generatedLeaf =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import a.Mod;",
"",
GENERATED_ANNOTATION,
"public abstract class DaggerHasUnusedModuleLeaf implements HasUnusedModuleLeaf {",
" public abstract static class Builder implements HasUnusedModuleLeaf.Builder {",
" protected Mod mod;",
"",
" protected b.Mod mod2;",
"",
" protected c.Mod mod3;",
" }",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerHasUnusedModuleLeaf")
.containsElementsIn(generatedLeaf);
filesToCompile.add(
JavaFileObjects.forSourceLines(
"test.Root",
"package test;",
"",
"import dagger.Component;",
"",
"@Component",
"interface Root {",
" HasUnusedModuleLeaf.Builder leaf();",
"}"));
JavaFileObject generatedRoot =
JavaFileObjects.forSourceLines(
"test.DaggerLeaf",
"package test;",
"",
"import a.Mod;",
"",
GENERATED_ANNOTATION,
"public final class DaggerRoot implements Root {",
" private final class HasUnusedModuleLeafBuilder",
" extends DaggerHasUnusedModuleLeaf.Builder {",
" @Override",
" public HasUnusedModuleLeaf build() {",
" if (mod == null) {",
" this.mod = new Mod();",
" }",
// Before this regression was fixed, `mod3` was instead `mod2`, since the `b.Mod` was
// pruned from the graph and did not need validation.
" if (mod3 == null) {",
" this.mod3 = new c.Mod();",
" }",
" return new HasUnusedModuleLeafImpl(mod, mod3);",
" }",
" }",
"}");
compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerRoot")
.containsElementsIn(generatedRoot);
}
private void createAncillaryClasses(
ImmutableList.Builder<JavaFileObject> filesBuilder, String... ancillaryClasses) {
for (String className : ancillaryClasses) {
filesBuilder.add(
JavaFileObjects.forSourceLines(
String.format("test.%s", className),
"package test;",
"",
String.format("class %s { }", className)));
}
}
private static Compilation compile(Iterable<JavaFileObject> files) {
return daggerCompiler()
.withOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE.javacopts())
.compile(files);
}
private static Compilation compileWithoutGuava(Iterable<JavaFileObject> files) {
return daggerCompiler()
.withOptions(
AHEAD_OF_TIME_SUBCOMPONENTS_MODE.javacopts().append(CLASS_PATH_WITHOUT_GUAVA_OPTION))
.compile(files);
}
}