• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.internal.codegen;
18 
19 import static com.google.testing.compile.CompilationSubject.assertThat;
20 import static dagger.internal.codegen.CompilerMode.AHEAD_OF_TIME_SUBCOMPONENTS_MODE;
21 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
22 import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
23 import static dagger.internal.codegen.Compilers.compilerWithOptions;
24 import static dagger.internal.codegen.Compilers.daggerCompiler;
25 import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
26 import static dagger.internal.codegen.GeneratedLines.GENERATION_OPTIONS_ANNOTATION;
27 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
28 
29 import com.google.common.collect.ImmutableList;
30 import com.google.testing.compile.Compilation;
31 import com.google.testing.compile.JavaFileObjects;
32 import javax.tools.JavaFileObject;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.junit.runners.JUnit4;
36 
37 @RunWith(JUnit4.class)
38 public final class AheadOfTimeSubcomponentsMultibindingsTest {
39   @Test
setMultibindings_contributionsInLeaf()40   public void setMultibindings_contributionsInLeaf() {
41     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
42     createSimplePackagePrivateClasses(filesToCompile, "InLeaf");
43     filesToCompile.add(
44         JavaFileObjects.forSourceLines(
45             "test.Leaf",
46             "package test;",
47             "",
48             "import dagger.Subcomponent;",
49             "import java.util.Set;",
50             "",
51             "@Subcomponent(modules = LeafModule.class)",
52             "interface Leaf {",
53             "  Set<InLeaf> contributionsInLeaf();",
54             "}"),
55         JavaFileObjects.forSourceLines(
56             "test.LeafModule",
57             "package test;",
58             "",
59             "import dagger.Module;",
60             "import dagger.Provides;",
61             "import dagger.multibindings.IntoSet;",
62             "",
63             "@Module",
64             "class LeafModule {",
65             "  @Provides",
66             "  @IntoSet",
67             "  static InLeaf provideInLeaf() {",
68             "    return new InLeaf();",
69             "  }",
70             "}"));
71     JavaFileObject generatedLeaf =
72         JavaFileObjects.forSourceLines(
73             "test.DaggerLeaf",
74             "package test;",
75             "",
76             "import com.google.common.collect.ImmutableSet;",
77             "import dagger.internal.GenerationOptions;",
78             "import java.util.Set;",
79             IMPORT_GENERATED_ANNOTATION,
80             "",
81             GENERATION_OPTIONS_ANNOTATION,
82             GENERATED_ANNOTATION,
83             "public abstract class DaggerLeaf implements Leaf {",
84             "  protected DaggerLeaf() {}",
85             "",
86             "  @Override",
87             "  public Set<InLeaf> contributionsInLeaf() {",
88             "    return ImmutableSet.<InLeaf>of(",
89             "        LeafModule_ProvideInLeafFactory.provideInLeaf());",
90             "  }",
91             "}");
92     Compilation compilation = compile(filesToCompile.build());
93     assertThat(compilation).succeededWithoutWarnings();
94     assertThat(compilation)
95         .generatedSourceFile("test.DaggerLeaf")
96         .hasSourceEquivalentTo(generatedLeaf);
97   }
98 
99   @Test
setMultibindings_contributionsInAncestorOnly()100   public void setMultibindings_contributionsInAncestorOnly() {
101     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
102     createSimplePackagePrivateClasses(filesToCompile, "InAncestor");
103     filesToCompile.add(
104         JavaFileObjects.forSourceLines(
105             "test.Leaf",
106             "package test;",
107             "",
108             "import dagger.Subcomponent;",
109             "import java.util.Set;",
110             "",
111             "@Subcomponent",
112             "interface Leaf {",
113             "  Set<InAncestor> contributionsInAncestor();",
114             "}"));
115     JavaFileObject generatedLeaf =
116         JavaFileObjects.forSourceLines(
117             "test.DaggerLeaf",
118             "package test;",
119             "",
120             "import dagger.internal.GenerationOptions;",
121             "import java.util.Set;",
122             IMPORT_GENERATED_ANNOTATION,
123             "",
124             GENERATION_OPTIONS_ANNOTATION,
125             GENERATED_ANNOTATION,
126             "public abstract class DaggerLeaf implements Leaf {",
127             "  protected DaggerLeaf() {}",
128             "",
129             "  @Override",
130             "  public abstract Set<InAncestor> contributionsInAncestor();",
131             "}");
132     Compilation compilation = compile(filesToCompile.build());
133     assertThat(compilation).succeededWithoutWarnings();
134     assertThat(compilation)
135         .generatedSourceFile("test.DaggerLeaf")
136         .hasSourceEquivalentTo(generatedLeaf);
137 
138     filesToCompile.add(
139         JavaFileObjects.forSourceLines(
140             "test.Ancestor",
141             "package test;",
142             "",
143             "import dagger.Subcomponent;",
144             "import java.util.Set;",
145             "",
146             "@Subcomponent(modules = AncestorModule.class)",
147             "interface Ancestor {",
148             "  Leaf leaf();",
149             "}"),
150         JavaFileObjects.forSourceLines(
151             "test.AncestorModule",
152             "package test;",
153             "",
154             "import com.google.common.collect.ImmutableSet;",
155             "import dagger.Module;",
156             "import dagger.Provides;",
157             "import dagger.multibindings.ElementsIntoSet;",
158             "import java.util.Set;",
159             "",
160             "@Module",
161             "class AncestorModule {",
162             "  @Provides",
163             "  @ElementsIntoSet",
164             "  static Set<InAncestor> provideInAncestors() {",
165             "    return ImmutableSet.of(new InAncestor(), new InAncestor());",
166             "  }",
167             "}"));
168     JavaFileObject generatedAncestor =
169         JavaFileObjects.forSourceLines(
170             "test.DaggerAncestor",
171             "package test;",
172             "",
173             "import com.google.common.collect.ImmutableSet;",
174             "import dagger.internal.GenerationOptions;",
175             "import java.util.Set;",
176             IMPORT_GENERATED_ANNOTATION,
177             "",
178             GENERATION_OPTIONS_ANNOTATION,
179             GENERATED_ANNOTATION,
180             "public abstract class DaggerAncestor implements Ancestor {",
181             "  protected DaggerAncestor() {}",
182             "",
183             "  protected abstract class LeafImpl extends DaggerLeaf {",
184             "    protected LeafImpl() {}",
185             "",
186             "    @Override",
187             "    public Set<InAncestor> contributionsInAncestor() {",
188             "      return ImmutableSet.<InAncestor>copyOf(",
189             "          AncestorModule_ProvideInAncestorsFactory.provideInAncestors());",
190             "    }",
191             "  }",
192             "}");
193     compilation = compile(filesToCompile.build());
194     assertThat(compilation).succeededWithoutWarnings();
195     assertThat(compilation)
196         .generatedSourceFile("test.DaggerAncestor")
197         .hasSourceEquivalentTo(generatedAncestor);
198   }
199 
200   @Test
setMultibindings_contributionsInLeafAndAncestor()201   public void setMultibindings_contributionsInLeafAndAncestor() {
202     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
203     createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
204     filesToCompile.add(
205         JavaFileObjects.forSourceLines(
206             "test.Leaf",
207             "package test;",
208             "",
209             "import dagger.Subcomponent;",
210             "import java.util.Set;",
211             "",
212             "@Subcomponent(modules = LeafModule.class)",
213             "interface Leaf {",
214             "  Set<InEachSubcomponent> contributionsInEachSubcomponent();",
215             "}"),
216         JavaFileObjects.forSourceLines(
217             "test.LeafModule",
218             "package test;",
219             "",
220             "import dagger.Module;",
221             "import dagger.Provides;",
222             "import dagger.multibindings.IntoSet;",
223             "",
224             "@Module",
225             "class LeafModule {",
226             "  @Provides",
227             "  @IntoSet",
228             "  static InEachSubcomponent provideInLeaf() {",
229             "    return new InEachSubcomponent();",
230             "  }",
231             "",
232             "  @Provides",
233             "  @IntoSet",
234             "  static InEachSubcomponent provideAnotherInLeaf() {",
235             "    return new InEachSubcomponent();",
236             "  }",
237             "}"));
238     JavaFileObject generatedLeaf =
239         JavaFileObjects.forSourceLines(
240             "test.DaggerLeaf",
241             "package test;",
242             "",
243             "import com.google.common.collect.ImmutableSet;",
244             "import dagger.internal.GenerationOptions;",
245             "import java.util.Set;",
246             IMPORT_GENERATED_ANNOTATION,
247             "",
248             GENERATION_OPTIONS_ANNOTATION,
249             GENERATED_ANNOTATION,
250             "public abstract class DaggerLeaf implements Leaf {",
251             "  protected DaggerLeaf() {}",
252             "",
253             "  @Override",
254             "  public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
255             "    return ImmutableSet.<InEachSubcomponent>of(",
256             "        LeafModule_ProvideInLeafFactory.provideInLeaf(),",
257             "        LeafModule_ProvideAnotherInLeafFactory.provideAnotherInLeaf());",
258             "  }",
259             "}");
260     Compilation compilation = compile(filesToCompile.build());
261     assertThat(compilation).succeededWithoutWarnings();
262     assertThat(compilation)
263         .generatedSourceFile("test.DaggerLeaf")
264         .hasSourceEquivalentTo(generatedLeaf);
265 
266     filesToCompile.add(
267         JavaFileObjects.forSourceLines(
268             "test.Ancestor",
269             "package test;",
270             "",
271             "import dagger.Subcomponent;",
272             "import java.util.Set;",
273             "",
274             "@Subcomponent(modules = AncestorModule.class)",
275             "interface Ancestor {",
276             "  Leaf leaf();",
277             "}"),
278         JavaFileObjects.forSourceLines(
279             "test.AncestorModule",
280             "package test;",
281             "",
282             "import com.google.common.collect.ImmutableSet;",
283             "import dagger.Module;",
284             "import dagger.Provides;",
285             "import dagger.multibindings.ElementsIntoSet;",
286             "import java.util.Set;",
287             "",
288             "@Module",
289             "class AncestorModule {",
290             "  @Provides",
291             "  @ElementsIntoSet",
292             "  static Set<InEachSubcomponent> provideInAncestor() {",
293             "    return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
294             "  }",
295             "}"));
296     JavaFileObject generatedAncestor =
297         JavaFileObjects.forSourceLines(
298             "test.DaggerAncestor",
299             "package test;",
300             "",
301             "import com.google.common.collect.ImmutableSet;",
302             "import dagger.internal.GenerationOptions;",
303             "import java.util.Set;",
304             IMPORT_GENERATED_ANNOTATION,
305             "",
306             GENERATION_OPTIONS_ANNOTATION,
307             GENERATED_ANNOTATION,
308             "public abstract class DaggerAncestor implements Ancestor {",
309             "  protected DaggerAncestor() {}",
310             "",
311             "  protected abstract class LeafImpl extends DaggerLeaf {",
312             "    protected LeafImpl() {}",
313             "",
314             "    @Override",
315             "    public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
316             "      return ImmutableSet.<InEachSubcomponent>builderWithExpectedSize(3)",
317             "          .addAll(AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
318             "          .addAll(super.contributionsInEachSubcomponent())",
319             "          .build();",
320             "    }",
321             "  }",
322             "}");
323     compilation = compile(filesToCompile.build());
324     assertThat(compilation).succeededWithoutWarnings();
325     assertThat(compilation)
326         .generatedSourceFile("test.DaggerAncestor")
327         .hasSourceEquivalentTo(generatedAncestor);
328   }
329 
330   @Test
setMultibindings_contributionsInLeafAndGrandAncestor()331   public void setMultibindings_contributionsInLeafAndGrandAncestor() {
332     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
333     createSimplePackagePrivateClasses(filesToCompile, "InLeafAndGrandAncestor");
334     filesToCompile.add(
335         JavaFileObjects.forSourceLines(
336             "test.Leaf",
337             "package test;",
338             "",
339             "import dagger.Subcomponent;",
340             "import java.util.Set;",
341             "",
342             "@Subcomponent(modules = LeafModule.class)",
343             "interface Leaf {",
344             "  Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
345             "}"),
346         JavaFileObjects.forSourceLines(
347             "test.LeafModule",
348             "package test;",
349             "",
350             "import dagger.Module;",
351             "import dagger.Provides;",
352             "import dagger.multibindings.IntoSet;",
353             "",
354             "@Module",
355             "class LeafModule {",
356             "  @Provides",
357             "  @IntoSet",
358             "  static InLeafAndGrandAncestor provideInLeaf() {",
359             "    return new InLeafAndGrandAncestor();",
360             "  }",
361             "",
362             "  @Provides",
363             "  @IntoSet",
364             "  static InLeafAndGrandAncestor provideAnotherInLeaf() {",
365             "    return new InLeafAndGrandAncestor();",
366             "  }",
367             "}"));
368     JavaFileObject generatedLeaf =
369         JavaFileObjects.forSourceLines(
370             "test.DaggerLeaf",
371             "package test;",
372             "",
373             "import com.google.common.collect.ImmutableSet;",
374             "import dagger.internal.GenerationOptions;",
375             "import java.util.Set;",
376             IMPORT_GENERATED_ANNOTATION,
377             "",
378             GENERATION_OPTIONS_ANNOTATION,
379             GENERATED_ANNOTATION,
380             "public abstract class DaggerLeaf implements Leaf {",
381             "  protected DaggerLeaf() {}",
382             "",
383             "  @Override",
384             "  public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
385             "    return ImmutableSet.<InLeafAndGrandAncestor>of(",
386             "        LeafModule_ProvideInLeafFactory.provideInLeaf(),",
387             "        LeafModule_ProvideAnotherInLeafFactory.provideAnotherInLeaf());",
388             "  }",
389             "}");
390     Compilation compilation = compile(filesToCompile.build());
391     assertThat(compilation).succeededWithoutWarnings();
392     assertThat(compilation)
393         .generatedSourceFile("test.DaggerLeaf")
394         .hasSourceEquivalentTo(generatedLeaf);
395 
396     filesToCompile.add(
397         JavaFileObjects.forSourceLines(
398             "test.Ancestor",
399             "package test;",
400             "",
401             "import dagger.Subcomponent;",
402             "import java.util.Set;",
403             "",
404             "@Subcomponent",
405             "interface Ancestor {",
406             "  Leaf leaf();",
407             "}"));
408     JavaFileObject generatedAncestor =
409         JavaFileObjects.forSourceLines(
410             "test.DaggerAncestor",
411             "package test;",
412             "",
413             "import dagger.internal.GenerationOptions;",
414             IMPORT_GENERATED_ANNOTATION,
415             "",
416             GENERATION_OPTIONS_ANNOTATION,
417             GENERATED_ANNOTATION,
418             "public abstract class DaggerAncestor implements Ancestor {",
419             "  protected DaggerAncestor() {}",
420             "",
421             "  protected abstract class LeafImpl extends DaggerLeaf {",
422             "    protected LeafImpl() {}",
423             "  }",
424             "}");
425     compilation = compile(filesToCompile.build());
426     assertThat(compilation).succeededWithoutWarnings();
427     assertThat(compilation)
428         .generatedSourceFile("test.DaggerAncestor")
429         .hasSourceEquivalentTo(generatedAncestor);
430 
431     filesToCompile.add(
432         JavaFileObjects.forSourceLines(
433             "test.GrandAncestor",
434             "package test;",
435             "",
436             "import dagger.Subcomponent;",
437             "import java.util.Set;",
438             "",
439             "@Subcomponent(modules = GrandAncestorModule.class)",
440             "interface GrandAncestor {",
441             "  Leaf leaf();",
442             "}"),
443         JavaFileObjects.forSourceLines(
444             "test.GrandAncestorModule",
445             "package test;",
446             "",
447             "import com.google.common.collect.ImmutableSet;",
448             "import dagger.Module;",
449             "import dagger.Provides;",
450             "import dagger.multibindings.ElementsIntoSet;",
451             "import java.util.Set;",
452             "",
453             "@Module",
454             "class GrandAncestorModule {",
455             "  @Provides",
456             "  @ElementsIntoSet",
457             "  static Set<InLeafAndGrandAncestor> provideInGrandAncestor() {",
458             "    return ImmutableSet.of(new InLeafAndGrandAncestor(),",
459             "        new InLeafAndGrandAncestor());",
460             "  }",
461             "}"));
462     JavaFileObject generatedGrandAncestor =
463         JavaFileObjects.forSourceLines(
464             "test.DaggerGrandAncestor",
465             "package test;",
466             "",
467             "import com.google.common.collect.ImmutableSet;",
468             "import dagger.internal.GenerationOptions;",
469             "import java.util.Set;",
470             IMPORT_GENERATED_ANNOTATION,
471             "",
472             GENERATION_OPTIONS_ANNOTATION,
473             GENERATED_ANNOTATION,
474             "public abstract class DaggerGrandAncestor implements GrandAncestor {",
475             "  protected DaggerGrandAncestor() {}",
476             "",
477             "  protected abstract class LeafImpl extends DaggerLeaf {",
478             "    protected LeafImpl() {}",
479             "",
480             "    @Override",
481             "    public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
482             "      return ImmutableSet.<InLeafAndGrandAncestor>builderWithExpectedSize(3)",
483             "          .addAll(GrandAncestorModule_ProvideInGrandAncestorFactory",
484             "              .provideInGrandAncestor())",
485             "          .addAll(super.contributionsInLeafAndGrandAncestor())",
486             "          .build();",
487             "    }",
488             "  }",
489             "}");
490     compilation = compile(filesToCompile.build());
491     assertThat(compilation).succeededWithoutWarnings();
492     assertThat(compilation)
493         .generatedSourceFile("test.DaggerGrandAncestor")
494         .hasSourceEquivalentTo(generatedGrandAncestor);
495   }
496 
497   @Test
setMultibindings_nonComponentMethodDependency()498   public void setMultibindings_nonComponentMethodDependency() {
499     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
500     createSimplePackagePrivateClasses(
501         filesToCompile, "InAllSubcomponents", "RequresInAllSubcomponentsSet");
502     filesToCompile.add(
503         JavaFileObjects.forSourceLines(
504             "test.Leaf",
505             "package test;",
506             "",
507             "import dagger.Subcomponent;",
508             "import java.util.Set;",
509             "",
510             "@Subcomponent(modules = LeafModule.class)",
511             "interface Leaf {",
512             "  RequresInAllSubcomponentsSet requiresNonComponentMethod();",
513             "}"),
514         JavaFileObjects.forSourceLines(
515             "test.LeafModule",
516             "package test;",
517             "",
518             "import dagger.Module;",
519             "import dagger.Provides;",
520             "import dagger.multibindings.IntoSet;",
521             "import java.util.Set;",
522             "",
523             "@Module",
524             "class LeafModule {",
525             "  @Provides",
526             "  @IntoSet",
527             "  static InAllSubcomponents provideInAllSubcomponents() {",
528             "    return new InAllSubcomponents();",
529             "  }",
530             "",
531             "  @Provides",
532             "  static RequresInAllSubcomponentsSet providesRequresInAllSubcomponentsSet(",
533             "      Set<InAllSubcomponents> inAllSubcomponents) {",
534             "    return new RequresInAllSubcomponentsSet();",
535             "  }",
536             "}"));
537     JavaFileObject generatedLeaf =
538         JavaFileObjects.forSourceLines(
539             "test.DaggerLeaf",
540             "package test;",
541             "",
542             "import com.google.common.collect.ImmutableSet;",
543             "import dagger.internal.GenerationOptions;",
544             "import java.util.Set;",
545             IMPORT_GENERATED_ANNOTATION,
546             "",
547             GENERATION_OPTIONS_ANNOTATION,
548             GENERATED_ANNOTATION,
549             "public abstract class DaggerLeaf implements Leaf {",
550             "  protected DaggerLeaf() {}",
551             "",
552             "  @Override",
553             "  public RequresInAllSubcomponentsSet requiresNonComponentMethod() {",
554             "    return LeafModule_ProvidesRequresInAllSubcomponentsSetFactory",
555             "        .providesRequresInAllSubcomponentsSet(getSetOfInAllSubcomponents());",
556             "  }",
557             "",
558             "  protected Set getSetOfInAllSubcomponents() {",
559             "    return ImmutableSet.<InAllSubcomponents>of(",
560             "        LeafModule_ProvideInAllSubcomponentsFactory",
561             "            .provideInAllSubcomponents());",
562             "  }",
563             "}");
564     Compilation compilation = compile(filesToCompile.build());
565     assertThat(compilation).succeededWithoutWarnings();
566     assertThat(compilation)
567         .generatedSourceFile("test.DaggerLeaf")
568         .hasSourceEquivalentTo(generatedLeaf);
569 
570     filesToCompile.add(
571         JavaFileObjects.forSourceLines(
572             "test.Ancestor",
573             "package test;",
574             "",
575             "import dagger.Subcomponent;",
576             "",
577             "@Subcomponent(modules = AncestorModule.class)",
578             "interface Ancestor {",
579             "  Leaf leaf();",
580             "}"),
581         JavaFileObjects.forSourceLines(
582             "test.AncestorModule",
583             "package test;",
584             "",
585             "import dagger.Module;",
586             "import dagger.Provides;",
587             "import dagger.multibindings.IntoSet;",
588             "",
589             "@Module",
590             "class AncestorModule {",
591             "  @Provides",
592             "  @IntoSet",
593             "  static InAllSubcomponents provideInAllSubcomponents() {",
594             "      return new InAllSubcomponents();",
595             "  }",
596             "}"));
597     JavaFileObject generatedAncestor =
598         JavaFileObjects.forSourceLines(
599             "test.DaggerAncestor",
600             "package test;",
601             "",
602             "import com.google.common.collect.ImmutableSet;",
603             "import dagger.internal.GenerationOptions;",
604             "import java.util.Set;",
605             IMPORT_GENERATED_ANNOTATION,
606             "",
607             GENERATION_OPTIONS_ANNOTATION,
608             GENERATED_ANNOTATION,
609             "public abstract class DaggerAncestor implements Ancestor {",
610             "  protected DaggerAncestor() {}",
611             "",
612             "  protected abstract class LeafImpl extends DaggerLeaf {",
613             "    protected LeafImpl() {}",
614             "",
615             "    @Override",
616             "    protected Set getSetOfInAllSubcomponents() {",
617             "      return ImmutableSet.<InAllSubcomponents>builderWithExpectedSize(2)",
618             "          .add(AncestorModule_ProvideInAllSubcomponentsFactory",
619             "              .provideInAllSubcomponents())",
620             "          .addAll(super.getSetOfInAllSubcomponents())",
621             "          .build();",
622             "    }",
623             "  }",
624             "}");
625     compilation = compile(filesToCompile.build());
626     assertThat(compilation).succeededWithoutWarnings();
627     assertThat(compilation)
628         .generatedSourceFile("test.DaggerAncestor")
629         .hasSourceEquivalentTo(generatedAncestor);
630   }
631 
632   @Test
setMultibindings_newSubclass()633   public void setMultibindings_newSubclass() {
634     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
635     createSimplePackagePrivateClasses(filesToCompile, "InAncestor", "RequiresInAncestorSet");
636     filesToCompile.add(
637         JavaFileObjects.forSourceLines(
638             "test.Leaf",
639             "package test;",
640             "",
641             "import dagger.Subcomponent;",
642             "",
643             "@Subcomponent",
644             "interface Leaf {",
645             "  RequiresInAncestorSet missingWithSetDependency();",
646             "}"));
647     JavaFileObject generatedLeaf =
648         JavaFileObjects.forSourceLines(
649             "test.DaggerLeaf",
650             "package test;",
651             "",
652             "import dagger.internal.GenerationOptions;",
653             IMPORT_GENERATED_ANNOTATION,
654             "",
655             GENERATION_OPTIONS_ANNOTATION,
656             GENERATED_ANNOTATION,
657             "public abstract class DaggerLeaf implements Leaf {",
658             "  protected DaggerLeaf() {}",
659             "",
660             "  @Override",
661             "  public abstract RequiresInAncestorSet missingWithSetDependency();",
662             "}");
663     Compilation compilation = compile(filesToCompile.build());
664     assertThat(compilation).succeededWithoutWarnings();
665     assertThat(compilation)
666         .generatedSourceFile("test.DaggerLeaf")
667         .hasSourceEquivalentTo(generatedLeaf);
668 
669     filesToCompile.add(
670         JavaFileObjects.forSourceLines(
671             "test.Ancestor",
672             "package test;",
673             "",
674             "import dagger.Subcomponent;",
675             "",
676             "@Subcomponent(modules = AncestorModule.class)",
677             "interface Ancestor {",
678             "  Leaf leaf();",
679             "}"),
680         JavaFileObjects.forSourceLines(
681             "test.AncestorModule",
682             "package test;",
683             "",
684             "import dagger.Module;",
685             "import dagger.Provides;",
686             "import dagger.multibindings.IntoSet;",
687             "import java.util.Set;",
688             "",
689             "@Module",
690             "class AncestorModule {",
691             "",
692             "  @Provides",
693             "  static RequiresInAncestorSet provideRequiresInAncestorSet(",
694             "      Set<InAncestor> inAncestors) {",
695             "    return new RequiresInAncestorSet();",
696             "  }",
697             "",
698             "  @Provides",
699             "  @IntoSet",
700             "  static InAncestor provideInAncestor() {",
701             "    return new InAncestor();",
702             "  }",
703             "}"));
704     JavaFileObject generatedAncestor =
705         JavaFileObjects.forSourceLines(
706             "test.DaggerAncestor",
707             "package test;",
708             "",
709             "import com.google.common.collect.ImmutableSet;",
710             "import dagger.internal.GenerationOptions;",
711             "import java.util.Set;",
712             IMPORT_GENERATED_ANNOTATION,
713             "",
714             GENERATION_OPTIONS_ANNOTATION,
715             GENERATED_ANNOTATION,
716             "public abstract class DaggerAncestor implements Ancestor {",
717             "  protected DaggerAncestor() {}",
718             "",
719             "  private RequiresInAncestorSet getRequiresInAncestorSet() {",
720             "    return AncestorModule_ProvideRequiresInAncestorSetFactory",
721             "        .provideRequiresInAncestorSet(getSetOfInAncestor());",
722             "  }",
723             "",
724             "  protected Set getSetOfInAncestor() {",
725             "    return ImmutableSet.<InAncestor>of(",
726             "        AncestorModule_ProvideInAncestorFactory.provideInAncestor());",
727             "  }",
728             "",
729             "  protected abstract class LeafImpl extends DaggerLeaf {",
730             "    protected LeafImpl() {}",
731             "",
732             "    @Override",
733             "    public final RequiresInAncestorSet missingWithSetDependency() {",
734             "      return DaggerAncestor.this.getRequiresInAncestorSet();",
735             "    }",
736             "  }",
737             "}");
738     compilation = compile(filesToCompile.build());
739     assertThat(compilation).succeededWithoutWarnings();
740     assertThat(compilation)
741         .generatedSourceFile("test.DaggerAncestor")
742         .hasSourceEquivalentTo(generatedAncestor);
743   }
744 
745   @Test
setMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor()746   public void setMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
747     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
748     createSimplePackagePrivateClasses(
749         filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
750     filesToCompile.add(
751         JavaFileObjects.forSourceLines(
752             "test.Leaf",
753             "package test;",
754             "",
755             "import dagger.Subcomponent;",
756             "import java.util.Set;",
757             "import javax.inject.Provider;",
758             "",
759             "@Subcomponent(modules = LeafModule.class)",
760             "interface Leaf {",
761             "  Set<Multibound> instance();",
762             "  MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
763             "}"),
764         JavaFileObjects.forSourceLines(
765             "test.LeafModule",
766             "package test;",
767             "",
768             "import dagger.Module;",
769             "import dagger.Provides;",
770             "import dagger.multibindings.IntoSet;",
771             "import java.util.Set;",
772             "",
773             "@Module",
774             "class LeafModule {",
775             "  @Provides",
776             "  @IntoSet",
777             "  static Multibound contribution() {",
778             "    return new Multibound();",
779             "  }",
780             "}"));
781     JavaFileObject generatedLeaf =
782         JavaFileObjects.forSourceLines(
783             "test.DaggerLeaf",
784             "package test;",
785             "",
786             "import com.google.common.collect.ImmutableSet;",
787             "import dagger.internal.GenerationOptions;",
788             "import java.util.Set;",
789             IMPORT_GENERATED_ANNOTATION,
790             "",
791             GENERATION_OPTIONS_ANNOTATION,
792             GENERATED_ANNOTATION,
793             "public abstract class DaggerLeaf implements Leaf {",
794             "  protected DaggerLeaf() {}",
795             "",
796             "  @Override",
797             "  public Set<Multibound> instance() {",
798             "    return ImmutableSet.<Multibound>of(",
799             "        LeafModule_ContributionFactory.contribution());",
800             "  }",
801             "",
802             "  @Override",
803             "  public abstract MissingInLeaf_WillDependOnFrameworkInstance",
804             "      willDependOnFrameworkInstance();",
805             "}");
806     Compilation compilation = compile(filesToCompile.build());
807     assertThat(compilation).succeededWithoutWarnings();
808     assertThat(compilation)
809         .generatedSourceFile("test.DaggerLeaf")
810         .hasSourceEquivalentTo(generatedLeaf);
811 
812     filesToCompile.add(
813         JavaFileObjects.forSourceLines(
814             "test.Ancestor",
815             "package test;",
816             "",
817             "import dagger.Subcomponent;",
818             "",
819             "@Subcomponent(modules = AncestorModule.class)",
820             "interface Ancestor {",
821             "  Leaf leaf();",
822             "}"),
823         JavaFileObjects.forSourceLines(
824             "test.AncestorModule",
825             "package test;",
826             "",
827             "import dagger.Module;",
828             "import dagger.Provides;",
829             "import dagger.multibindings.Multibinds;",
830             "import java.util.Set;",
831             "import javax.inject.Provider;",
832             "",
833             "@Module",
834             "interface AncestorModule {",
835             "  @Provides",
836             "  static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
837             "      Provider<Set<Multibound>> frameworkInstance) {",
838             "    return null;",
839             "  }",
840             "",
841             "  @Multibinds Set<Multibound> multibinds();",
842             "}"));
843     JavaFileObject generatedAncestor =
844         JavaFileObjects.forSourceLines(
845             "test.DaggerAncestor",
846             "package test;",
847             "",
848             "import dagger.internal.GenerationOptions;",
849             "import dagger.internal.SetFactory;",
850             "import java.util.Set;",
851             IMPORT_GENERATED_ANNOTATION,
852             "import javax.inject.Provider;",
853             "",
854             GENERATION_OPTIONS_ANNOTATION,
855             GENERATED_ANNOTATION,
856             "public abstract class DaggerAncestor implements Ancestor {",
857             "  protected DaggerAncestor() {}",
858             "",
859             "  protected abstract class LeafImpl extends DaggerLeaf {",
860             "    private Provider<Set<Multibound>> setOfMultiboundProvider;",
861             "",
862             "    protected LeafImpl() {}",
863             "",
864             "    protected void configureInitialization() { ",
865             "      initialize();",
866             "    }",
867             "",
868             "    @SuppressWarnings(\"unchecked\")",
869             "    private void initialize() { ",
870             "      this.setOfMultiboundProvider =",
871             "          SetFactory.<Multibound>builder(1, 0)",
872             "              .addProvider(LeafModule_ContributionFactory.create())",
873             "              .build();",
874             "    }",
875             "",
876             "    protected Provider getSetOfMultiboundProvider() {",
877             "      return setOfMultiboundProvider;",
878             "    }",
879             "",
880             "    @Override",
881             "    public final MissingInLeaf_WillDependOnFrameworkInstance ",
882             "        willDependOnFrameworkInstance() {",
883             "      return AncestorModule_ProvidedInAncestorFactory.providedInAncestor(",
884             "          getSetOfMultiboundProvider());",
885             "    }",
886             "  }",
887             "}");
888     compilation = compile(filesToCompile.build());
889     assertThat(compilation).succeededWithoutWarnings();
890     assertThat(compilation)
891         .generatedSourceFile("test.DaggerAncestor")
892         .hasSourceEquivalentTo(generatedAncestor);
893   }
894 
895   @Test
missingMultibindingInLeaf_onlyContributionsInAncestor_notReModifiedInRoot()896   public void missingMultibindingInLeaf_onlyContributionsInAncestor_notReModifiedInRoot() {
897     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
898     filesToCompile.add(
899         JavaFileObjects.forSourceLines(
900             "test.Leaf",
901             "package test;",
902             "",
903             "import dagger.Subcomponent;",
904             "import java.util.Set;",
905             "import javax.inject.Provider;",
906             "",
907             "@Subcomponent",
908             "interface Leaf {",
909             "  Set<Object> set();",
910             "}"));
911     JavaFileObject generatedLeaf =
912         JavaFileObjects.forSourceLines(
913             "test.DaggerLeaf",
914             "package test;",
915             "",
916             "import dagger.internal.GenerationOptions;",
917             "import java.util.Set;",
918             IMPORT_GENERATED_ANNOTATION,
919             "",
920             GENERATION_OPTIONS_ANNOTATION,
921             GENERATED_ANNOTATION,
922             "public abstract class DaggerLeaf implements Leaf {",
923             "  protected DaggerLeaf() {}",
924             "",
925             "  @Override",
926             "  public abstract Set<Object> set();",
927             "}");
928     Compilation compilation = compile(filesToCompile.build());
929     assertThat(compilation).succeededWithoutWarnings();
930     assertThat(compilation)
931         .generatedSourceFile("test.DaggerLeaf")
932         .hasSourceEquivalentTo(generatedLeaf);
933 
934     filesToCompile.add(
935         JavaFileObjects.forSourceLines(
936             "test.Ancestor",
937             "package test;",
938             "",
939             "import dagger.Subcomponent;",
940             "import java.util.Set;",
941             "",
942             "@Subcomponent(modules = AncestorModule.class)",
943             "interface Ancestor {",
944             "  Leaf leaf();",
945             "}"),
946         JavaFileObjects.forSourceLines(
947             "test.AncestorModule",
948             "package test;",
949             "",
950             "import dagger.Module;",
951             "import dagger.Provides;",
952             "import dagger.multibindings.IntoSet;",
953             "",
954             "@Module",
955             "class AncestorModule {",
956             "  @Provides",
957             "  @IntoSet",
958             "  static Object onlyContribution() {",
959             "    return new Object();",
960             "  }",
961             "}"));
962     JavaFileObject generatedAncestor =
963         JavaFileObjects.forSourceLines(
964             "test.DaggerAncestor",
965             "package test;",
966             "",
967             "import com.google.common.collect.ImmutableSet;",
968             "import dagger.internal.GenerationOptions;",
969             "import java.util.Set;",
970             IMPORT_GENERATED_ANNOTATION,
971             "",
972             GENERATION_OPTIONS_ANNOTATION,
973             GENERATED_ANNOTATION,
974             "public abstract class DaggerAncestor implements Ancestor {",
975             "  protected DaggerAncestor() {}",
976             "",
977             "  protected abstract class LeafImpl extends DaggerLeaf {",
978             "    protected LeafImpl() {}",
979             "",
980             "    @Override",
981             "    public Set<Object> set() {",
982             "      return ImmutableSet.<Object>of(",
983             "          AncestorModule_OnlyContributionFactory.onlyContribution());",
984             "    }",
985             "  }",
986             "}");
987     compilation = compile(filesToCompile.build());
988     assertThat(compilation).succeededWithoutWarnings();
989     assertThat(compilation)
990         .generatedSourceFile("test.DaggerAncestor")
991         .hasSourceEquivalentTo(generatedAncestor);
992 
993     filesToCompile.add(
994         JavaFileObjects.forSourceLines(
995             "test.Root",
996             "package test;",
997             "",
998             "import dagger.Component;",
999             "",
1000             "@Component",
1001             "interface Root {",
1002             "  Ancestor ancestor();",
1003             "}"));
1004     JavaFileObject generatedRoot =
1005         JavaFileObjects.forSourceLines(
1006             "test.DaggerRoot",
1007             "package test;",
1008             "",
1009             IMPORT_GENERATED_ANNOTATION,
1010             "",
1011             GENERATED_ANNOTATION,
1012             "final class DaggerRoot implements Root {",
1013             "  private DaggerRoot() {}",
1014             "",
1015             "  public static Builder builder() {",
1016             "    return new Builder();",
1017             "  }",
1018             "",
1019             "  public static Root create() {",
1020             "    return new Builder().build();",
1021             "  }",
1022             "",
1023             "  @Override",
1024             "  public Ancestor ancestor() {",
1025             "    return new AncestorImpl();",
1026             "  }",
1027             "",
1028             "  static final class Builder {",
1029             "    private Builder() {}",
1030             "",
1031             "    public Root build() {",
1032             "      return new DaggerRoot();",
1033             "    }",
1034             "  }",
1035             "",
1036             "  protected final class AncestorImpl extends DaggerAncestor {",
1037             "    private AncestorImpl() {}",
1038             "",
1039             "    @Override",
1040             "    public Leaf leaf() {",
1041             "      return new LeafImpl();",
1042             "    }",
1043             "",
1044             "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
1045             "      private LeafImpl() {}",
1046             // This tests a regression case where Dagger used to reimplement Leaf.set(), even though
1047             // there were no new contributions, because the state change from missing ->
1048             // multibinding wasn't properly recorded
1049             "    }",
1050             "  }",
1051             "}");
1052     compilation = compile(filesToCompile.build());
1053     assertThat(compilation).succeededWithoutWarnings();
1054     assertThat(compilation)
1055         .generatedSourceFile("test.DaggerRoot")
1056         .hasSourceEquivalentTo(generatedRoot);
1057   }
1058 
1059   @Test
setMultibindings_contributionsInLeafAndAncestor_frameworkInstances()1060   public void setMultibindings_contributionsInLeafAndAncestor_frameworkInstances() {
1061     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1062     createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
1063     filesToCompile.add(
1064         JavaFileObjects.forSourceLines(
1065             "test.Leaf",
1066             "package test;",
1067             "",
1068             "import dagger.Subcomponent;",
1069             "import java.util.Set;",
1070             "import javax.inject.Provider;",
1071             "",
1072             "@Subcomponent(modules = LeafModule.class)",
1073             "interface Leaf {",
1074             "  Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent();",
1075             "}"),
1076         JavaFileObjects.forSourceLines(
1077             "test.LeafModule",
1078             "package test;",
1079             "",
1080             "import dagger.Module;",
1081             "import dagger.Provides;",
1082             "import dagger.multibindings.IntoSet;",
1083             "",
1084             "@Module",
1085             "class LeafModule {",
1086             "  @Provides",
1087             "  @IntoSet",
1088             "  static InEachSubcomponent provideInLeaf() {",
1089             "    return new InEachSubcomponent();",
1090             "  }",
1091             "",
1092             "  @Provides",
1093             "  @IntoSet",
1094             "  static InEachSubcomponent provideAnotherInLeaf() {",
1095             "    return new InEachSubcomponent();",
1096             "  }",
1097             "}"));
1098     JavaFileObject generatedLeaf =
1099         JavaFileObjects.forSourceLines(
1100             "test.DaggerLeaf",
1101             "package test;",
1102             "",
1103             "import dagger.internal.GenerationOptions;",
1104             "import dagger.internal.SetFactory;",
1105             "import java.util.Set;",
1106             IMPORT_GENERATED_ANNOTATION,
1107             "import javax.inject.Provider;",
1108             "",
1109             GENERATION_OPTIONS_ANNOTATION,
1110             GENERATED_ANNOTATION,
1111             "public abstract class DaggerLeaf implements Leaf {",
1112             "  private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider;",
1113             "",
1114             "  protected DaggerLeaf() {}",
1115             "",
1116             "  protected void configureInitialization() {",
1117             "    initialize();",
1118             "  }",
1119             "",
1120             "  @SuppressWarnings(\"unchecked\")",
1121             "  private void initialize() {",
1122             "    this.setOfInEachSubcomponentProvider =",
1123             "        SetFactory.<InEachSubcomponent>builder(2, 0)",
1124             "            .addProvider(LeafModule_ProvideInLeafFactory.create())",
1125             "            .addProvider(LeafModule_ProvideAnotherInLeafFactory.create())",
1126             "            .build();",
1127             "  }",
1128             "",
1129             "  @Override",
1130             "  public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
1131             "    return setOfInEachSubcomponentProvider;",
1132             "  }",
1133             "}");
1134     Compilation compilation = compile(filesToCompile.build());
1135     assertThat(compilation).succeededWithoutWarnings();
1136     assertThat(compilation)
1137         .generatedSourceFile("test.DaggerLeaf")
1138         .hasSourceEquivalentTo(generatedLeaf);
1139 
1140     filesToCompile.add(
1141         JavaFileObjects.forSourceLines(
1142             "test.Ancestor",
1143             "package test;",
1144             "",
1145             "import dagger.Subcomponent;",
1146             "import java.util.Set;",
1147             "",
1148             "@Subcomponent(modules = AncestorModule.class)",
1149             "interface Ancestor {",
1150             "  Leaf leaf();",
1151             "}"),
1152         JavaFileObjects.forSourceLines(
1153             "test.AncestorModule",
1154             "package test;",
1155             "",
1156             "import com.google.common.collect.ImmutableSet;",
1157             "import dagger.Module;",
1158             "import dagger.Provides;",
1159             "import dagger.multibindings.ElementsIntoSet;",
1160             "import java.util.Set;",
1161             "",
1162             "@Module",
1163             "class AncestorModule {",
1164             "  @Provides",
1165             "  @ElementsIntoSet",
1166             "  static Set<InEachSubcomponent> provideInAncestor() {",
1167             "    return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
1168             "  }",
1169             "}"));
1170     JavaFileObject generatedAncestor =
1171         JavaFileObjects.forSourceLines(
1172             "test.DaggerAncestor",
1173             "package test;",
1174             "",
1175             "import dagger.internal.DelegateFactory;",
1176             "import dagger.internal.GenerationOptions;",
1177             "import dagger.internal.SetFactory;",
1178             "import java.util.Set;",
1179             IMPORT_GENERATED_ANNOTATION,
1180             "import javax.inject.Provider;",
1181             "",
1182             GENERATION_OPTIONS_ANNOTATION,
1183             GENERATED_ANNOTATION,
1184             "public abstract class DaggerAncestor implements Ancestor {",
1185             "  protected DaggerAncestor() {}",
1186             "",
1187             "  protected abstract class LeafImpl extends DaggerLeaf {",
1188             "    private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider = ",
1189             "        new DelegateFactory<>();",
1190             "",
1191             "    protected LeafImpl() {}",
1192             "",
1193             "    @Override",
1194             "    protected void configureInitialization() {",
1195             "      super.configureInitialization();",
1196             "      initialize();",
1197             "    }",
1198             "",
1199             "    @SuppressWarnings(\"unchecked\")",
1200             "    private void initialize() {",
1201             "      DelegateFactory.setDelegate(",
1202             "          setOfInEachSubcomponentProvider,",
1203             "          SetFactory.<InEachSubcomponent>builder(0, 2)",
1204             "              .addCollectionProvider(super.contributionsInEachSubcomponent())",
1205             "              .addCollectionProvider(",
1206             "                  AncestorModule_ProvideInAncestorFactory.create())",
1207             "              .build());",
1208             "    }",
1209             "",
1210             "    @Override",
1211             "    public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
1212             "      return setOfInEachSubcomponentProvider;",
1213             "    }",
1214             "  }",
1215             "}");
1216     compilation = compile(filesToCompile.build());
1217     assertThat(compilation).succeededWithoutWarnings();
1218     assertThat(compilation)
1219         .generatedSourceFile("test.DaggerAncestor")
1220         .hasSourceEquivalentTo(generatedAncestor);
1221   }
1222 
1223   @Test
mapMultibindings_contributionsInLeaf()1224   public void mapMultibindings_contributionsInLeaf() {
1225     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1226     createSimplePackagePrivateClasses(filesToCompile, "InLeaf");
1227     filesToCompile.add(
1228         JavaFileObjects.forSourceLines(
1229             "test.Leaf",
1230             "package test;",
1231             "",
1232             "import dagger.Subcomponent;",
1233             "import java.util.Map;",
1234             "",
1235             "@Subcomponent(modules = LeafModule.class)",
1236             "interface Leaf {",
1237             "  Map<String, InLeaf> contributionsInLeaf();",
1238             "}"),
1239         JavaFileObjects.forSourceLines(
1240             "test.LeafModule",
1241             "package test;",
1242             "",
1243             "import dagger.Module;",
1244             "import dagger.Provides;",
1245             "import dagger.multibindings.IntoMap;",
1246             "import dagger.multibindings.StringKey;",
1247             "import java.util.Map;",
1248             "",
1249             "@Module",
1250             "class LeafModule {",
1251             "  @Provides",
1252             "  @IntoMap",
1253             "  @StringKey(\"leafmodule\")",
1254             "  static InLeaf provideInLeaf() {",
1255             "    return new InLeaf();",
1256             "  }",
1257             "}"));
1258     JavaFileObject generatedLeaf =
1259         JavaFileObjects.forSourceLines(
1260             "test.DaggerLeaf",
1261             "package test;",
1262             "",
1263             "import com.google.common.collect.ImmutableMap;",
1264             "import dagger.internal.GenerationOptions;",
1265             "import java.util.Map;",
1266             IMPORT_GENERATED_ANNOTATION,
1267             "",
1268             GENERATION_OPTIONS_ANNOTATION,
1269             GENERATED_ANNOTATION,
1270             "public abstract class DaggerLeaf implements Leaf {",
1271             "  protected DaggerLeaf() {}",
1272             "",
1273             "  @Override",
1274             "  public Map<String, InLeaf> contributionsInLeaf() {",
1275             "    return ImmutableMap.<String, InLeaf>of(",
1276             "        \"leafmodule\",",
1277             "        LeafModule_ProvideInLeafFactory.provideInLeaf());",
1278             "  }",
1279             "}");
1280     Compilation compilation = compile(filesToCompile.build());
1281     assertThat(compilation).succeededWithoutWarnings();
1282     assertThat(compilation)
1283         .generatedSourceFile("test.DaggerLeaf")
1284         .hasSourceEquivalentTo(generatedLeaf);
1285   }
1286 
1287   @Test
mapMultibindings_contributionsInAncestorOnly()1288   public void mapMultibindings_contributionsInAncestorOnly() {
1289     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1290     createSimplePackagePrivateClasses(filesToCompile, "InAncestor");
1291     filesToCompile.add(
1292         JavaFileObjects.forSourceLines(
1293             "test.Leaf",
1294             "package test;",
1295             "",
1296             "import dagger.Subcomponent;",
1297             "import java.util.Map;",
1298             "",
1299             "@Subcomponent",
1300             "interface Leaf {",
1301             "  Map<String, InAncestor> contributionsInAncestor();",
1302             "}"));
1303     JavaFileObject generatedLeaf =
1304         JavaFileObjects.forSourceLines(
1305             "test.DaggerLeaf",
1306             "package test;",
1307             "",
1308             "import dagger.internal.GenerationOptions;",
1309             "import java.util.Map;",
1310             IMPORT_GENERATED_ANNOTATION,
1311             "",
1312             GENERATION_OPTIONS_ANNOTATION,
1313             GENERATED_ANNOTATION,
1314             "public abstract class DaggerLeaf implements Leaf {",
1315             "  protected DaggerLeaf() {}",
1316             "",
1317             "  @Override",
1318             "  public abstract Map<String, InAncestor> contributionsInAncestor();",
1319             "}");
1320     Compilation compilation = compile(filesToCompile.build());
1321     assertThat(compilation).succeededWithoutWarnings();
1322     assertThat(compilation)
1323         .generatedSourceFile("test.DaggerLeaf")
1324         .hasSourceEquivalentTo(generatedLeaf);
1325 
1326     filesToCompile.add(
1327         JavaFileObjects.forSourceLines(
1328             "test.Ancestor",
1329             "package test;",
1330             "",
1331             "import dagger.Subcomponent;",
1332             "",
1333             "@Subcomponent(modules = AncestorModule.class)",
1334             "interface Ancestor {",
1335             "  Leaf leaf();",
1336             "}"),
1337         JavaFileObjects.forSourceLines(
1338             "test.AncestorModule",
1339             "package test;",
1340             "",
1341             "import dagger.Module;",
1342             "import dagger.Provides;",
1343             "import dagger.multibindings.IntoMap;",
1344             "import dagger.multibindings.StringKey;",
1345             "import java.util.Map;",
1346             "",
1347             "@Module",
1348             "class AncestorModule {",
1349             "  @Provides",
1350             "  @IntoMap",
1351             "  @StringKey(\"ancestormodule\")",
1352             "  static InAncestor provideInAncestor() {",
1353             "    return new InAncestor();",
1354             "  }",
1355             "}"));
1356     JavaFileObject generatedAncestor =
1357         JavaFileObjects.forSourceLines(
1358             "test.DaggerAncestor",
1359             "package test;",
1360             "",
1361             "import com.google.common.collect.ImmutableMap;",
1362             "import dagger.internal.GenerationOptions;",
1363             "import java.util.Map;",
1364             IMPORT_GENERATED_ANNOTATION,
1365             "",
1366             GENERATION_OPTIONS_ANNOTATION,
1367             GENERATED_ANNOTATION,
1368             "public abstract class DaggerAncestor implements Ancestor {",
1369             "  protected DaggerAncestor() {}",
1370             "",
1371             "  protected abstract class LeafImpl extends DaggerLeaf {",
1372             "    protected LeafImpl() {}",
1373             "",
1374             "    @Override",
1375             "    public Map<String, InAncestor> contributionsInAncestor() {",
1376             "      return ImmutableMap.<String, InAncestor>of(\"ancestormodule\",",
1377             "          AncestorModule_ProvideInAncestorFactory.provideInAncestor());",
1378             "    }",
1379             "  }",
1380             "}");
1381     compilation = compile(filesToCompile.build());
1382     assertThat(compilation).succeededWithoutWarnings();
1383     assertThat(compilation)
1384         .generatedSourceFile("test.DaggerAncestor")
1385         .hasSourceEquivalentTo(generatedAncestor);
1386   }
1387 
1388   @Test
mapMultibindings_contributionsInLeafAndAncestor()1389   public void mapMultibindings_contributionsInLeafAndAncestor() {
1390     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1391     createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
1392     filesToCompile.add(
1393         JavaFileObjects.forSourceLines(
1394             "test.Leaf",
1395             "package test;",
1396             "",
1397             "import dagger.Subcomponent;",
1398             "import java.util.Map;",
1399             "",
1400             "@Subcomponent(modules = LeafModule.class)",
1401             "interface Leaf {",
1402             "  Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
1403             "}"),
1404         JavaFileObjects.forSourceLines(
1405             "test.LeafModule",
1406             "package test;",
1407             "",
1408             "import dagger.Module;",
1409             "import dagger.Provides;",
1410             "import dagger.multibindings.IntoMap;",
1411             "import dagger.multibindings.StringKey;",
1412             "import java.util.Map;",
1413             "",
1414             "@Module",
1415             "class LeafModule {",
1416             "  @Provides",
1417             "  @IntoMap",
1418             "  @StringKey(\"leafmodule\")",
1419             "  static InEachSubcomponent provideInLeaf() {",
1420             "    return new InEachSubcomponent();",
1421             "  }",
1422             "}"));
1423     JavaFileObject generatedLeaf =
1424         JavaFileObjects.forSourceLines(
1425             "test.DaggerLeaf",
1426             "package test;",
1427             "",
1428             "import com.google.common.collect.ImmutableMap;",
1429             "import dagger.internal.GenerationOptions;",
1430             "import java.util.Map;",
1431             IMPORT_GENERATED_ANNOTATION,
1432             "",
1433             GENERATION_OPTIONS_ANNOTATION,
1434             GENERATED_ANNOTATION,
1435             "public abstract class DaggerLeaf implements Leaf {",
1436             "  protected DaggerLeaf() {}",
1437             "",
1438             "  @Override",
1439             "  public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
1440             "    return ImmutableMap.<String, InEachSubcomponent>of(",
1441             "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
1442             "  }",
1443             "}");
1444     Compilation compilation = compile(filesToCompile.build());
1445     assertThat(compilation).succeededWithoutWarnings();
1446     assertThat(compilation)
1447         .generatedSourceFile("test.DaggerLeaf")
1448         .hasSourceEquivalentTo(generatedLeaf);
1449 
1450     filesToCompile.add(
1451         JavaFileObjects.forSourceLines(
1452             "test.Ancestor",
1453             "package test;",
1454             "",
1455             "import dagger.Subcomponent;",
1456             "",
1457             "@Subcomponent(modules = AncestorModule.class)",
1458             "interface Ancestor {",
1459             "  Leaf leaf();",
1460             "}"),
1461         JavaFileObjects.forSourceLines(
1462             "test.AncestorModule",
1463             "package test;",
1464             "",
1465             "import dagger.Module;",
1466             "import dagger.Provides;",
1467             "import dagger.multibindings.IntoMap;",
1468             "import dagger.multibindings.StringKey;",
1469             "import java.util.Map;",
1470             "",
1471             "@Module",
1472             "class AncestorModule {",
1473             "  @Provides",
1474             "  @IntoMap",
1475             "  @StringKey(\"ancestormodule\")",
1476             "  static InEachSubcomponent provideInAncestor() {",
1477             "    return new InEachSubcomponent();",
1478             "  }",
1479             "}"));
1480     JavaFileObject generatedAncestor =
1481         JavaFileObjects.forSourceLines(
1482             "test.DaggerAncestor",
1483             "package test;",
1484             "",
1485             "import com.google.common.collect.ImmutableMap;",
1486             "import dagger.internal.GenerationOptions;",
1487             "import java.util.Map;",
1488             IMPORT_GENERATED_ANNOTATION,
1489             "",
1490             GENERATION_OPTIONS_ANNOTATION,
1491             GENERATED_ANNOTATION,
1492             "public abstract class DaggerAncestor implements Ancestor {",
1493             "  protected DaggerAncestor() {}",
1494             "",
1495             "  protected abstract class LeafImpl extends DaggerLeaf {",
1496             "    protected LeafImpl() {}",
1497             "",
1498             "    @Override",
1499             "    public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
1500             "      return ImmutableMap.<String, InEachSubcomponent>builderWithExpectedSize(2)",
1501             "          .put(\"ancestormodule\",",
1502             "              AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
1503             "          .putAll(super.contributionsInEachSubcomponent())",
1504             "          .build();",
1505             "    }",
1506             "  }",
1507             "}");
1508     compilation = compile(filesToCompile.build());
1509     assertThat(compilation).succeededWithoutWarnings();
1510     assertThat(compilation)
1511         .generatedSourceFile("test.DaggerAncestor")
1512         .hasSourceEquivalentTo(generatedAncestor);
1513   }
1514 
1515   @Test
mapMultibindings_contributionsInLeafAndAncestor_frameworkInstance()1516   public void mapMultibindings_contributionsInLeafAndAncestor_frameworkInstance() {
1517     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1518     createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
1519     filesToCompile.add(
1520         JavaFileObjects.forSourceLines(
1521             "test.Leaf",
1522             "package test;",
1523             "",
1524             "import dagger.Subcomponent;",
1525             "import java.util.Map;",
1526             "import javax.inject.Provider;",
1527             "",
1528             "@Subcomponent(modules = LeafModule.class)",
1529             "interface Leaf {",
1530             "  Provider<Map<String, InEachSubcomponent>> contributionsInEachSubcomponent();",
1531             "}"),
1532         JavaFileObjects.forSourceLines(
1533             "test.LeafModule",
1534             "package test;",
1535             "",
1536             "import dagger.Module;",
1537             "import dagger.Provides;",
1538             "import dagger.multibindings.IntoMap;",
1539             "import dagger.multibindings.StringKey;",
1540             "import java.util.Map;",
1541             "",
1542             "@Module",
1543             "class LeafModule {",
1544             "  @Provides",
1545             "  @IntoMap",
1546             "  @StringKey(\"leafmodule\")",
1547             "  static InEachSubcomponent provideInLeaf() {",
1548             "    return new InEachSubcomponent();",
1549             "  }",
1550             "}"));
1551     JavaFileObject generatedLeaf =
1552         JavaFileObjects.forSourceLines(
1553             "test.DaggerLeaf",
1554             "package test;",
1555             "",
1556             "import dagger.internal.GenerationOptions;",
1557             "import dagger.internal.MapFactory;",
1558             "import java.util.Map;",
1559             IMPORT_GENERATED_ANNOTATION,
1560             "import javax.inject.Provider;",
1561             "",
1562             GENERATION_OPTIONS_ANNOTATION,
1563             GENERATED_ANNOTATION,
1564             "public abstract class DaggerLeaf implements Leaf {",
1565             "  private Provider<Map<String, InEachSubcomponent>> ",
1566             "    mapOfStringAndInEachSubcomponentProvider;",
1567             "",
1568             "  protected DaggerLeaf() {}",
1569             "",
1570             "  protected void configureInitialization() {",
1571             "    initialize();",
1572             "  }",
1573             "",
1574             "  @SuppressWarnings(\"unchecked\")",
1575             "  private void initialize() {",
1576             "    this.mapOfStringAndInEachSubcomponentProvider =",
1577             "        MapFactory.<String, InEachSubcomponent>builder(1)",
1578             "            .put(\"leafmodule\", LeafModule_ProvideInLeafFactory.create())",
1579             "            .build();",
1580             "  }",
1581             "",
1582             "  @Override",
1583             "  public Provider<Map<String, InEachSubcomponent>> ",
1584             "      contributionsInEachSubcomponent() {",
1585             "    return mapOfStringAndInEachSubcomponentProvider;",
1586             "  }",
1587             "}");
1588     Compilation compilation = compile(filesToCompile.build());
1589     assertThat(compilation).succeededWithoutWarnings();
1590     assertThat(compilation)
1591         .generatedSourceFile("test.DaggerLeaf")
1592         .hasSourceEquivalentTo(generatedLeaf);
1593 
1594     filesToCompile.add(
1595         JavaFileObjects.forSourceLines(
1596             "test.Ancestor",
1597             "package test;",
1598             "",
1599             "import dagger.Subcomponent;",
1600             "",
1601             "@Subcomponent(modules = AncestorModule.class)",
1602             "interface Ancestor {",
1603             "  Leaf leaf();",
1604             "}"),
1605         JavaFileObjects.forSourceLines(
1606             "test.AncestorModule",
1607             "package test;",
1608             "",
1609             "import dagger.Module;",
1610             "import dagger.Provides;",
1611             "import dagger.multibindings.IntoMap;",
1612             "import dagger.multibindings.StringKey;",
1613             "import java.util.Map;",
1614             "",
1615             "@Module",
1616             "class AncestorModule {",
1617             "  @Provides",
1618             "  @IntoMap",
1619             "  @StringKey(\"ancestormodule\")",
1620             "  static InEachSubcomponent provideInAncestor() {",
1621             "    return new InEachSubcomponent();",
1622             "  }",
1623             "}"));
1624     JavaFileObject generatedAncestor =
1625         JavaFileObjects.forSourceLines(
1626             "test.DaggerAncestor",
1627             "package test;",
1628             "",
1629             "import dagger.internal.DelegateFactory;",
1630             "import dagger.internal.GenerationOptions;",
1631             "import dagger.internal.MapFactory;",
1632             "import java.util.Map;",
1633             IMPORT_GENERATED_ANNOTATION,
1634             "import javax.inject.Provider;",
1635             "",
1636             GENERATION_OPTIONS_ANNOTATION,
1637             GENERATED_ANNOTATION,
1638             "public abstract class DaggerAncestor implements Ancestor {",
1639             "  protected DaggerAncestor() {}",
1640             "",
1641             "  protected abstract class LeafImpl extends DaggerLeaf {",
1642             "    private Provider<Map<String, InEachSubcomponent>> ",
1643             "      mapOfStringAndInEachSubcomponentProvider = new DelegateFactory<>();",
1644             "",
1645             "    protected LeafImpl() {}",
1646             "",
1647             "    @Override",
1648             "    protected void configureInitialization() { ",
1649             "      super.configureInitialization();",
1650             "      initialize();",
1651             "    }",
1652             "",
1653             "    @SuppressWarnings(\"unchecked\")",
1654             "    private void initialize() { ",
1655             "      DelegateFactory.setDelegate(",
1656             "          mapOfStringAndInEachSubcomponentProvider,",
1657             "          MapFactory.<String, InEachSubcomponent>builder(2)",
1658             "              .putAll(super.contributionsInEachSubcomponent())",
1659             "              .put(",
1660             "                  \"ancestormodule\",",
1661             "                  AncestorModule_ProvideInAncestorFactory.create())",
1662             "              .build());",
1663             "    }",
1664             "",
1665             "    @Override",
1666             "    public Provider<Map<String, InEachSubcomponent>> ",
1667             "        contributionsInEachSubcomponent() {",
1668             "      return mapOfStringAndInEachSubcomponentProvider;",
1669             "    }",
1670             "  }",
1671             "}");
1672     compilation = compile(filesToCompile.build());
1673     assertThat(compilation).succeededWithoutWarnings();
1674     assertThat(compilation)
1675         .generatedSourceFile("test.DaggerAncestor")
1676         .hasSourceEquivalentTo(generatedAncestor);
1677   }
1678 
1679   @Test
mapMultibindings_contributionsInLeafAndGrandAncestor()1680   public void mapMultibindings_contributionsInLeafAndGrandAncestor() {
1681     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1682     createSimplePackagePrivateClasses(filesToCompile, "InLeafAndGrandAncestor");
1683     filesToCompile.add(
1684         JavaFileObjects.forSourceLines(
1685             "test.Leaf",
1686             "package test;",
1687             "",
1688             "import dagger.Subcomponent;",
1689             "import java.util.Map;",
1690             "",
1691             "@Subcomponent(modules = LeafModule.class)",
1692             "interface Leaf {",
1693             "  Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
1694             "}"),
1695         JavaFileObjects.forSourceLines(
1696             "test.LeafModule",
1697             "package test;",
1698             "",
1699             "import dagger.Module;",
1700             "import dagger.Provides;",
1701             "import dagger.multibindings.IntoMap;",
1702             "import dagger.multibindings.StringKey;",
1703             "import java.util.Map;",
1704             "",
1705             "@Module",
1706             "class LeafModule {",
1707             "  @Provides",
1708             "  @IntoMap",
1709             "  @StringKey(\"leafmodule\")",
1710             "  static InLeafAndGrandAncestor provideInLeaf() {",
1711             "    return new InLeafAndGrandAncestor();",
1712             "  }",
1713             "}"));
1714     JavaFileObject generatedLeaf =
1715         JavaFileObjects.forSourceLines(
1716             "test.DaggerLeaf",
1717             "package test;",
1718             "",
1719             "import com.google.common.collect.ImmutableMap;",
1720             "import dagger.internal.GenerationOptions;",
1721             "import java.util.Map;",
1722             IMPORT_GENERATED_ANNOTATION,
1723             "",
1724             GENERATION_OPTIONS_ANNOTATION,
1725             GENERATED_ANNOTATION,
1726             "public abstract class DaggerLeaf implements Leaf {",
1727             "  protected DaggerLeaf() {}",
1728             "",
1729             "  @Override",
1730             "  public Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
1731             "    return ImmutableMap.<String, InLeafAndGrandAncestor>of(",
1732             "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
1733             "  }",
1734             "}");
1735     Compilation compilation = compile(filesToCompile.build());
1736     assertThat(compilation).succeededWithoutWarnings();
1737     assertThat(compilation)
1738         .generatedSourceFile("test.DaggerLeaf")
1739         .hasSourceEquivalentTo(generatedLeaf);
1740 
1741     filesToCompile.add(
1742         JavaFileObjects.forSourceLines(
1743             "test.Ancestor",
1744             "package test;",
1745             "",
1746             "import dagger.Subcomponent;",
1747             "",
1748             "@Subcomponent",
1749             "interface Ancestor {",
1750             "  Leaf leaf();",
1751             "}"));
1752     JavaFileObject generatedAncestor =
1753         JavaFileObjects.forSourceLines(
1754             "test.DaggerAncestor",
1755             "package test;",
1756             "",
1757             "import dagger.internal.GenerationOptions;",
1758             IMPORT_GENERATED_ANNOTATION,
1759             "",
1760             GENERATION_OPTIONS_ANNOTATION,
1761             GENERATED_ANNOTATION,
1762             "public abstract class DaggerAncestor implements Ancestor {",
1763             "  protected DaggerAncestor() {}",
1764             "",
1765             "  protected abstract class LeafImpl extends DaggerLeaf {",
1766             "    protected LeafImpl() {}",
1767             "  }",
1768             "}");
1769     compilation = compile(filesToCompile.build());
1770     assertThat(compilation).succeededWithoutWarnings();
1771     assertThat(compilation)
1772         .generatedSourceFile("test.DaggerAncestor")
1773         .hasSourceEquivalentTo(generatedAncestor);
1774 
1775     filesToCompile.add(
1776         JavaFileObjects.forSourceLines(
1777             "test.GrandAncestor",
1778             "package test;",
1779             "",
1780             "import dagger.Subcomponent;",
1781             "",
1782             "@Subcomponent(modules = GrandAncestorModule.class)",
1783             "interface GrandAncestor {",
1784             "  Ancestor ancestor();",
1785             "}"),
1786         JavaFileObjects.forSourceLines(
1787             "test.GrandAncestorModule",
1788             "package test;",
1789             "",
1790             "import dagger.Module;",
1791             "import dagger.Provides;",
1792             "import dagger.multibindings.IntoMap;",
1793             "import dagger.multibindings.StringKey;",
1794             "import java.util.Map;",
1795             "",
1796             "@Module",
1797             "class GrandAncestorModule {",
1798             "  @Provides",
1799             "  @IntoMap",
1800             "  @StringKey(\"grandancestormodule\")",
1801             "  static InLeafAndGrandAncestor provideInGrandAncestor() {",
1802             "    return new InLeafAndGrandAncestor();",
1803             "  }",
1804             "}"));
1805     JavaFileObject generatedGrandAncestor =
1806         JavaFileObjects.forSourceLines(
1807             "test.DaggerGrandAncestor",
1808             "package test;",
1809             "",
1810             "import com.google.common.collect.ImmutableMap;",
1811             "import dagger.internal.GenerationOptions;",
1812             "import java.util.Map;",
1813             IMPORT_GENERATED_ANNOTATION,
1814             "",
1815             GENERATION_OPTIONS_ANNOTATION,
1816             GENERATED_ANNOTATION,
1817             "public abstract class DaggerGrandAncestor implements GrandAncestor {",
1818             "  protected DaggerGrandAncestor() {}",
1819             "",
1820             "  protected abstract class AncestorImpl extends DaggerAncestor {",
1821             "    protected AncestorImpl() {}",
1822             "",
1823             "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
1824             "      protected LeafImpl() {}",
1825             "",
1826             "      @Override",
1827             "      public Map<String, InLeafAndGrandAncestor>",
1828             "          contributionsInLeafAndGrandAncestor() {",
1829             "        return",
1830             "            ImmutableMap.<String, InLeafAndGrandAncestor>builderWithExpectedSize(2)",
1831             "                .put(\"grandancestormodule\",",
1832             "                    GrandAncestorModule_ProvideInGrandAncestorFactory",
1833             "                        .provideInGrandAncestor())",
1834             "                .putAll(super.contributionsInLeafAndGrandAncestor())",
1835             "                .build();",
1836             "      }",
1837             "    }",
1838             "  }",
1839             "}");
1840     compilation = compile(filesToCompile.build());
1841     assertThat(compilation).succeededWithoutWarnings();
1842     assertThat(compilation)
1843         .generatedSourceFile("test.DaggerGrandAncestor")
1844         .hasSourceEquivalentTo(generatedGrandAncestor);
1845   }
1846 
1847   @Test
mapMultibindings_contributionsInLeafAndAncestorWithoutGuava()1848   public void mapMultibindings_contributionsInLeafAndAncestorWithoutGuava() {
1849     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1850     createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
1851     filesToCompile.add(
1852         JavaFileObjects.forSourceLines(
1853             "test.Leaf",
1854             "package test;",
1855             "",
1856             "import dagger.Subcomponent;",
1857             "import java.util.Map;",
1858             "",
1859             "@Subcomponent(modules = LeafModule.class)",
1860             "interface Leaf {",
1861             "  Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
1862             "}"),
1863         JavaFileObjects.forSourceLines(
1864             "test.LeafModule",
1865             "package test;",
1866             "",
1867             "import dagger.Module;",
1868             "import dagger.Provides;",
1869             "import dagger.multibindings.IntoMap;",
1870             "import dagger.multibindings.StringKey;",
1871             "import java.util.Map;",
1872             "",
1873             "@Module",
1874             "class LeafModule {",
1875             "  @Provides",
1876             "  @IntoMap",
1877             "  @StringKey(\"leafmodule\")",
1878             "  static InEachSubcomponent provideInLeaf() {",
1879             "    return new InEachSubcomponent();",
1880             "  }",
1881             "}"));
1882     JavaFileObject generatedLeaf =
1883         JavaFileObjects.forSourceLines(
1884             "test.DaggerLeaf",
1885             "package test;",
1886             "",
1887             "import dagger.internal.GenerationOptions;",
1888             "import java.util.Collections;",
1889             "import java.util.Map",
1890             IMPORT_GENERATED_ANNOTATION,
1891             "",
1892             GENERATION_OPTIONS_ANNOTATION,
1893             GENERATED_ANNOTATION,
1894             "public abstract class DaggerLeaf implements Leaf {",
1895             "  protected DaggerLeaf() {}",
1896             "",
1897             "  @Override",
1898             "  public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
1899             "    return Collections.<String, InEachSubcomponent>singletonMap(",
1900             "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
1901             "  }",
1902             "}");
1903     Compilation compilation = compileWithoutGuava(filesToCompile.build());
1904     assertThat(compilation).succeededWithoutWarnings();
1905     assertThat(compilation)
1906         .generatedSourceFile("test.DaggerLeaf")
1907         .hasSourceEquivalentTo(generatedLeaf);
1908 
1909     filesToCompile.add(
1910         JavaFileObjects.forSourceLines(
1911             "test.Ancestor",
1912             "package test;",
1913             "",
1914             "import dagger.Subcomponent;",
1915             "",
1916             "@Subcomponent(modules = AncestorModule.class)",
1917             "interface Ancestor {",
1918             "  Leaf leaf();",
1919             "}"),
1920         JavaFileObjects.forSourceLines(
1921             "test.AncestorModule",
1922             "package test;",
1923             "",
1924             "import dagger.Module;",
1925             "import dagger.Provides;",
1926             "import dagger.multibindings.IntoMap;",
1927             "import dagger.multibindings.StringKey;",
1928             "import java.util.Map;",
1929             "",
1930             "@Module",
1931             "class AncestorModule {",
1932             "  @Provides",
1933             "  @IntoMap",
1934             "  @StringKey(\"ancestormodule\")",
1935             "  static InEachSubcomponent provideInAncestor() {",
1936             "    return new InEachSubcomponent();",
1937             "  }",
1938             "}"));
1939     JavaFileObject generatedAncestor =
1940         JavaFileObjects.forSourceLines(
1941             "test.DaggerAncestor",
1942             "package test;",
1943             "",
1944             "import dagger.internal.GenerationOptions;",
1945             "import dagger.internal.MapBuilder;",
1946             "import java.util.Map;",
1947             IMPORT_GENERATED_ANNOTATION,
1948             "",
1949             GENERATION_OPTIONS_ANNOTATION,
1950             GENERATED_ANNOTATION,
1951             "public abstract class DaggerAncestor implements Ancestor {",
1952             "  protected DaggerAncestor() {}",
1953             "",
1954             "  protected abstract class LeafImpl extends DaggerLeaf {",
1955             "    protected LeafImpl() {}",
1956             "",
1957             "    @Override",
1958             "    public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
1959             "      return MapBuilder.<String, InEachSubcomponent>newMapBuilder(2)",
1960             "          .put(\"ancestormodule\",",
1961             "              AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
1962             "          .putAll(super.contributionsInEachSubcomponent())",
1963             "          .build();",
1964             "    }",
1965             "  }",
1966             "}");
1967     compilation = compileWithoutGuava(filesToCompile.build());
1968     assertThat(compilation).succeededWithoutWarnings();
1969     assertThat(compilation)
1970         .generatedSourceFile("test.DaggerAncestor")
1971         .hasSourceEquivalentTo(generatedAncestor);
1972   }
1973 
1974   @Test
mapMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor()1975   public void mapMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
1976     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
1977     createSimplePackagePrivateClasses(
1978         filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
1979     filesToCompile.add(
1980         JavaFileObjects.forSourceLines(
1981             "test.Leaf",
1982             "package test;",
1983             "",
1984             "import dagger.Subcomponent;",
1985             "import java.util.Map;",
1986             "import javax.inject.Provider;",
1987             "",
1988             "@Subcomponent(modules = LeafModule.class)",
1989             "interface Leaf {",
1990             "  Map<Integer, Multibound> instance();",
1991             "  MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
1992             "}"),
1993         JavaFileObjects.forSourceLines(
1994             "test.LeafModule",
1995             "package test;",
1996             "",
1997             "import dagger.Module;",
1998             "import dagger.Provides;",
1999             "import dagger.multibindings.IntKey;",
2000             "import dagger.multibindings.IntoMap;",
2001             "import java.util.Map;",
2002             "",
2003             "@Module",
2004             "class LeafModule {",
2005             "  @Provides",
2006             "  @IntoMap",
2007             "  @IntKey(111)",
2008             "  static Multibound contribution() {",
2009             "    return new Multibound();",
2010             "  }",
2011             "}"));
2012     JavaFileObject generatedLeaf =
2013         JavaFileObjects.forSourceLines(
2014             "test.DaggerLeaf",
2015             "package test;",
2016             "",
2017             "import com.google.common.collect.ImmutableMap;",
2018             "import dagger.internal.GenerationOptions;",
2019             "import java.util.Map;",
2020             IMPORT_GENERATED_ANNOTATION,
2021             "",
2022             GENERATION_OPTIONS_ANNOTATION,
2023             GENERATED_ANNOTATION,
2024             "public abstract class DaggerLeaf implements Leaf {",
2025             "  protected DaggerLeaf() {}",
2026             "",
2027             "  @Override",
2028             "  public Map<Integer, Multibound> instance() {",
2029             "    return ImmutableMap.<Integer, Multibound>of(",
2030             "        111, LeafModule_ContributionFactory.contribution());",
2031             "  }",
2032             "",
2033             "  @Override",
2034             "  public abstract MissingInLeaf_WillDependOnFrameworkInstance",
2035             "      willDependOnFrameworkInstance();",
2036             "}");
2037     Compilation compilation = compile(filesToCompile.build());
2038     assertThat(compilation).succeededWithoutWarnings();
2039     assertThat(compilation)
2040         .generatedSourceFile("test.DaggerLeaf")
2041         .hasSourceEquivalentTo(generatedLeaf);
2042 
2043     filesToCompile.add(
2044         JavaFileObjects.forSourceLines(
2045             "test.Ancestor",
2046             "package test;",
2047             "",
2048             "import dagger.Subcomponent;",
2049             "",
2050             "@Subcomponent(modules = AncestorModule.class)",
2051             "interface Ancestor {",
2052             "  Leaf leaf();",
2053             "}"),
2054         JavaFileObjects.forSourceLines(
2055             "test.AncestorModule",
2056             "package test;",
2057             "",
2058             "import dagger.Module;",
2059             "import dagger.Provides;",
2060             "import dagger.multibindings.Multibinds;",
2061             "import java.util.Map;",
2062             "import javax.inject.Provider;",
2063             "",
2064             "@Module",
2065             "interface AncestorModule {",
2066             "  @Provides",
2067             "  static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
2068             "      Provider<Map<Integer, Multibound>> frameworkInstance) {",
2069             "    return null;",
2070             "  }",
2071             "",
2072             "  @Multibinds Map<Integer, Multibound> multibinds();",
2073             "}"));
2074     JavaFileObject generatedAncestor =
2075         JavaFileObjects.forSourceLines(
2076             "test.DaggerAncestor",
2077             "package test;",
2078             "",
2079             "import dagger.internal.GenerationOptions;",
2080             "import dagger.internal.MapFactory;",
2081             "import java.util.Map;",
2082             IMPORT_GENERATED_ANNOTATION,
2083             "import javax.inject.Provider;",
2084             "",
2085             GENERATION_OPTIONS_ANNOTATION,
2086             GENERATED_ANNOTATION,
2087             "public abstract class DaggerAncestor implements Ancestor {",
2088             "  protected DaggerAncestor() {}",
2089             "",
2090             "  protected abstract class LeafImpl extends DaggerLeaf {",
2091             "    private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider;",
2092             "",
2093             "    protected LeafImpl() {}",
2094             "",
2095             "    protected void configureInitialization() { ",
2096             "      initialize();",
2097             "    }",
2098             "",
2099             "    @SuppressWarnings(\"unchecked\")",
2100             "    private void initialize() { ",
2101             "      this.mapOfIntegerAndMultiboundProvider =",
2102             "          MapFactory.<Integer, Multibound>builder(1)",
2103             "              .put(111, LeafModule_ContributionFactory.create())",
2104             "              .build();",
2105             "    }",
2106             "",
2107             "    protected Provider getMapOfIntegerAndMultiboundProvider() {",
2108             "      return mapOfIntegerAndMultiboundProvider;",
2109             "    }",
2110             "",
2111             "    @Override",
2112             "    public final MissingInLeaf_WillDependOnFrameworkInstance ",
2113             "        willDependOnFrameworkInstance() {",
2114             "      return AncestorModule_ProvidedInAncestorFactory.providedInAncestor(",
2115             "          getMapOfIntegerAndMultiboundProvider());",
2116             "    }",
2117             "  }",
2118             "}");
2119     compilation = compile(filesToCompile.build());
2120     assertThat(compilation).succeededWithoutWarnings();
2121     assertThat(compilation)
2122         .generatedSourceFile("test.DaggerAncestor")
2123         .hasSourceEquivalentTo(generatedAncestor);
2124   }
2125 
2126   @Test
emptyMultibinds_set()2127   public void emptyMultibinds_set() {
2128     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2129     createSimplePackagePrivateClasses(filesToCompile, "Multibound");
2130     filesToCompile.add(
2131         JavaFileObjects.forSourceLines(
2132             "test.LeafModule",
2133             "package test;",
2134             "",
2135             "import dagger.Module;",
2136             "import dagger.multibindings.Multibinds;",
2137             "import java.util.Set;",
2138             "",
2139             "@Module",
2140             "interface LeafModule {",
2141             "  @Multibinds",
2142             "  Set<Multibound> set();",
2143             "}"),
2144         JavaFileObjects.forSourceLines(
2145             "test.Leaf",
2146             "package test;",
2147             "",
2148             "import dagger.Subcomponent;",
2149             "import java.util.Set;",
2150             "",
2151             "@Subcomponent(modules = LeafModule.class)",
2152             "interface Leaf {",
2153             "  Set<Multibound> set();",
2154             "}"));
2155     JavaFileObject generatedLeaf =
2156         JavaFileObjects.forSourceLines(
2157             "test.DaggerLeaf",
2158             "package test;",
2159             "",
2160             "import com.google.common.collect.ImmutableSet;",
2161             "import dagger.internal.GenerationOptions;",
2162             "import java.util.Set;",
2163             IMPORT_GENERATED_ANNOTATION,
2164             "",
2165             GENERATION_OPTIONS_ANNOTATION,
2166             GENERATED_ANNOTATION,
2167             "public abstract class DaggerLeaf implements Leaf {",
2168             "  protected DaggerLeaf() {}",
2169             "",
2170             "  @Override",
2171             "  public Set<Multibound> set() {",
2172             "    return ImmutableSet.<Multibound>of();",
2173             "  }",
2174             "}");
2175     Compilation compilation = compile(filesToCompile.build());
2176     assertThat(compilation).succeededWithoutWarnings();
2177     assertThat(compilation)
2178         .generatedSourceFile("test.DaggerLeaf")
2179         .hasSourceEquivalentTo(generatedLeaf);
2180 
2181     filesToCompile.add(
2182         JavaFileObjects.forSourceLines(
2183             "test.Ancestor",
2184             "package test;",
2185             "",
2186             "import dagger.Subcomponent;",
2187             "",
2188             "@Subcomponent(modules = AncestorModule.class)",
2189             "interface Ancestor {",
2190             "  Leaf leaf();",
2191             "}"),
2192         JavaFileObjects.forSourceLines(
2193             "test.AncestorModule",
2194             "package test;",
2195             "",
2196             "import dagger.Module;",
2197             "import dagger.Provides;",
2198             "import dagger.multibindings.IntoSet;",
2199             "",
2200             "@Module",
2201             "class AncestorModule {",
2202             "  @Provides",
2203             "  @IntoSet",
2204             "  static Multibound fromAncestor() {",
2205             "    return new Multibound();",
2206             "  }",
2207             "}"));
2208     JavaFileObject generatedAncestor =
2209         JavaFileObjects.forSourceLines(
2210             "test.DaggerAncestor",
2211             "package test;",
2212             "",
2213             "import com.google.common.collect.ImmutableSet;",
2214             "import dagger.internal.GenerationOptions;",
2215             "import java.util.Set;",
2216             IMPORT_GENERATED_ANNOTATION,
2217             "",
2218             GENERATION_OPTIONS_ANNOTATION,
2219             GENERATED_ANNOTATION,
2220             "public abstract class DaggerAncestor implements Ancestor {",
2221             "  protected DaggerAncestor() {}",
2222             "",
2223             "  protected abstract class LeafImpl extends DaggerLeaf {",
2224             "    protected LeafImpl() {}",
2225             "",
2226             "    @Override",
2227             "    public Set<Multibound> set() {",
2228             "      return ImmutableSet.<Multibound>of(",
2229             "          AncestorModule_FromAncestorFactory.fromAncestor());",
2230             "    }",
2231             "  }",
2232             "}");
2233     compilation = compile(filesToCompile.build());
2234     assertThat(compilation).succeededWithoutWarnings();
2235     assertThat(compilation)
2236         .generatedSourceFile("test.DaggerAncestor")
2237         .hasSourceEquivalentTo(generatedAncestor);
2238   }
2239 
2240   @Test
emptyMultibinds_set_frameworkInstance()2241   public void emptyMultibinds_set_frameworkInstance() {
2242     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2243     createSimplePackagePrivateClasses(filesToCompile, "Multibound");
2244     filesToCompile.add(
2245         JavaFileObjects.forSourceLines(
2246             "test.LeafModule",
2247             "package test;",
2248             "",
2249             "import dagger.Module;",
2250             "import dagger.multibindings.Multibinds;",
2251             "import java.util.Set;",
2252             "",
2253             "@Module",
2254             "interface LeafModule {",
2255             "  @Multibinds",
2256             "  Set<Multibound> set();",
2257             "}"),
2258         JavaFileObjects.forSourceLines(
2259             "test.Leaf",
2260             "package test;",
2261             "",
2262             "import dagger.Subcomponent;",
2263             "import java.util.Set;",
2264             "import javax.inject.Provider;",
2265             "",
2266             "@Subcomponent(modules = LeafModule.class)",
2267             "interface Leaf {",
2268             "  Provider<Set<Multibound>> set();",
2269             "}"));
2270     JavaFileObject generatedLeaf =
2271         JavaFileObjects.forSourceLines(
2272             "test.DaggerLeaf",
2273             "package test;",
2274             "",
2275             "import dagger.internal.GenerationOptions;",
2276             "import dagger.internal.SetFactory;",
2277             "import java.util.Set;",
2278             IMPORT_GENERATED_ANNOTATION,
2279             "import javax.inject.Provider;",
2280             "",
2281             GENERATION_OPTIONS_ANNOTATION,
2282             GENERATED_ANNOTATION,
2283             "public abstract class DaggerLeaf implements Leaf {",
2284             "  protected DaggerLeaf() {}",
2285             "",
2286             "  @Override",
2287             "  public Provider<Set<Multibound>> set() {",
2288             "    return SetFactory.<Multibound>empty();",
2289             "  }",
2290             "}");
2291     Compilation compilation = compile(filesToCompile.build());
2292     assertThat(compilation).succeededWithoutWarnings();
2293     assertThat(compilation)
2294         .generatedSourceFile("test.DaggerLeaf")
2295         .hasSourceEquivalentTo(generatedLeaf);
2296 
2297     filesToCompile.add(
2298         JavaFileObjects.forSourceLines(
2299             "test.Ancestor",
2300             "package test;",
2301             "",
2302             "import dagger.Subcomponent;",
2303             "",
2304             "@Subcomponent(modules = AncestorModule.class)",
2305             "interface Ancestor {",
2306             "  Leaf leaf();",
2307             "}"),
2308         JavaFileObjects.forSourceLines(
2309             "test.AncestorModule",
2310             "package test;",
2311             "",
2312             "import dagger.Module;",
2313             "import dagger.Provides;",
2314             "import dagger.multibindings.IntoSet;",
2315             "",
2316             "@Module",
2317             "class AncestorModule {",
2318             "  @Provides",
2319             "  @IntoSet",
2320             "  static Multibound fromAncestor() {",
2321             "    return new Multibound();",
2322             "  }",
2323             "}"));
2324     JavaFileObject generatedAncestor =
2325         JavaFileObjects.forSourceLines(
2326             "test.DaggerAncestor",
2327             "package test;",
2328             "",
2329             "import dagger.internal.DelegateFactory;",
2330             "import dagger.internal.GenerationOptions;",
2331             "import dagger.internal.SetFactory;",
2332             "import java.util.Set;",
2333             IMPORT_GENERATED_ANNOTATION,
2334             "import javax.inject.Provider;",
2335             "",
2336             GENERATION_OPTIONS_ANNOTATION,
2337             GENERATED_ANNOTATION,
2338             "public abstract class DaggerAncestor implements Ancestor {",
2339             "  protected DaggerAncestor() {}",
2340             "",
2341             "  protected abstract class LeafImpl extends DaggerLeaf {",
2342             "    private Provider<Set<Multibound>> setOfMultiboundProvider =",
2343             "        new DelegateFactory<>();",
2344             "",
2345             "    protected LeafImpl() {}",
2346             "",
2347             "    protected void configureInitialization() {",
2348             "      initialize();",
2349             "    }",
2350             "",
2351             "    @SuppressWarnings(\"unchecked\")",
2352             "    private void initialize() {",
2353             "      DelegateFactory.setDelegate(",
2354             "          setOfMultiboundProvider,",
2355             "          SetFactory.<Multibound>builder(1, 0)",
2356             "              .addProvider(AncestorModule_FromAncestorFactory.create())",
2357             "              .build());",
2358             "    }",
2359             "",
2360             "    @Override",
2361             "    public Provider<Set<Multibound>> set() {",
2362             "      return setOfMultiboundProvider;",
2363             "    }",
2364             "  }",
2365             "}");
2366     compilation = compile(filesToCompile.build());
2367     assertThat(compilation).succeededWithoutWarnings();
2368     assertThat(compilation)
2369         .generatedSourceFile("test.DaggerAncestor")
2370         .hasSourceEquivalentTo(generatedAncestor);
2371   }
2372 
2373   @Test
emptyMultibinds_map()2374   public void emptyMultibinds_map() {
2375     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2376     createSimplePackagePrivateClasses(filesToCompile, "Multibound");
2377     filesToCompile.add(
2378         JavaFileObjects.forSourceLines(
2379             "test.LeafModule",
2380             "package test;",
2381             "",
2382             "import dagger.Module;",
2383             "import dagger.multibindings.Multibinds;",
2384             "import java.util.Map;",
2385             "",
2386             "@Module",
2387             "interface LeafModule {",
2388             "  @Multibinds",
2389             "  Map<Integer, Multibound> map();",
2390             "}"),
2391         JavaFileObjects.forSourceLines(
2392             "test.Leaf",
2393             "package test;",
2394             "",
2395             "import dagger.Subcomponent;",
2396             "import java.util.Map;",
2397             "",
2398             "@Subcomponent(modules = LeafModule.class)",
2399             "interface Leaf {",
2400             "  Map<Integer, Multibound> map();",
2401             "}"));
2402     JavaFileObject generatedLeaf =
2403         JavaFileObjects.forSourceLines(
2404             "test.DaggerLeaf",
2405             "package test;",
2406             "",
2407             "import com.google.common.collect.ImmutableMap;",
2408             "import dagger.internal.GenerationOptions;",
2409             "import java.util.Map;",
2410             IMPORT_GENERATED_ANNOTATION,
2411             "",
2412             GENERATION_OPTIONS_ANNOTATION,
2413             GENERATED_ANNOTATION,
2414             "public abstract class DaggerLeaf implements Leaf {",
2415             "  protected DaggerLeaf() {}",
2416             "",
2417             "  @Override",
2418             "  public Map<Integer, Multibound> map() {",
2419             "    return ImmutableMap.<Integer, Multibound>of();",
2420             "  }",
2421             "}");
2422     Compilation compilation = compile(filesToCompile.build());
2423     assertThat(compilation).succeededWithoutWarnings();
2424     assertThat(compilation)
2425         .generatedSourceFile("test.DaggerLeaf")
2426         .hasSourceEquivalentTo(generatedLeaf);
2427 
2428     filesToCompile.add(
2429         JavaFileObjects.forSourceLines(
2430             "test.Ancestor",
2431             "package test;",
2432             "",
2433             "import dagger.Subcomponent;",
2434             "",
2435             "@Subcomponent(modules = AncestorModule.class)",
2436             "interface Ancestor {",
2437             "  Leaf leaf();",
2438             "}"),
2439         JavaFileObjects.forSourceLines(
2440             "test.AncestorModule",
2441             "package test;",
2442             "",
2443             "import dagger.Module;",
2444             "import dagger.Provides;",
2445             "import dagger.multibindings.IntKey;",
2446             "import dagger.multibindings.IntoMap;",
2447             "",
2448             "@Module",
2449             "class AncestorModule {",
2450             "  @Provides",
2451             "  @IntoMap",
2452             "  @IntKey(111)",
2453             "  static Multibound fromAncestor() {",
2454             "    return new Multibound();",
2455             "  }",
2456             "}"));
2457     JavaFileObject generatedAncestor =
2458         JavaFileObjects.forSourceLines(
2459             "test.DaggerAncestor",
2460             "package test;",
2461             "",
2462             "import com.google.common.collect.ImmutableMap;",
2463             "import dagger.internal.GenerationOptions;",
2464             "import java.util.Map;",
2465             IMPORT_GENERATED_ANNOTATION,
2466             "",
2467             GENERATION_OPTIONS_ANNOTATION,
2468             GENERATED_ANNOTATION,
2469             "public abstract class DaggerAncestor implements Ancestor {",
2470             "  protected DaggerAncestor() {}",
2471             "",
2472             "  protected abstract class LeafImpl extends DaggerLeaf {",
2473             "    protected LeafImpl() {}",
2474             "",
2475             "    @Override",
2476             "    public Map<Integer, Multibound> map() {",
2477             "      return ImmutableMap.<Integer, Multibound>of(",
2478             "          111, AncestorModule_FromAncestorFactory.fromAncestor());",
2479             "    }",
2480             "  }",
2481             "}");
2482     compilation = compile(filesToCompile.build());
2483     assertThat(compilation).succeededWithoutWarnings();
2484     assertThat(compilation)
2485         .generatedSourceFile("test.DaggerAncestor")
2486         .hasSourceEquivalentTo(generatedAncestor);
2487   }
2488 
2489   @Test
emptyMultibinds_map_frameworkInstance()2490   public void emptyMultibinds_map_frameworkInstance() {
2491     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2492     createSimplePackagePrivateClasses(filesToCompile, "Multibound");
2493     filesToCompile.add(
2494         JavaFileObjects.forSourceLines(
2495             "test.LeafModule",
2496             "package test;",
2497             "",
2498             "import dagger.Module;",
2499             "import dagger.multibindings.Multibinds;",
2500             "import java.util.Map;",
2501             "",
2502             "@Module",
2503             "interface LeafModule {",
2504             "  @Multibinds",
2505             "  Map<Integer, Multibound> map();",
2506             "}"),
2507         JavaFileObjects.forSourceLines(
2508             "test.Leaf",
2509             "package test;",
2510             "",
2511             "import dagger.Subcomponent;",
2512             "import java.util.Map;",
2513             "import javax.inject.Provider;",
2514             "",
2515             "@Subcomponent(modules = LeafModule.class)",
2516             "interface Leaf {",
2517             "  Provider<Map<Integer, Multibound>> map();",
2518             "}"));
2519     JavaFileObject generatedLeaf =
2520         JavaFileObjects.forSourceLines(
2521             "test.DaggerLeaf",
2522             "package test;",
2523             "",
2524             "import dagger.internal.GenerationOptions;",
2525             "import dagger.internal.MapFactory;",
2526             "import java.util.Map;",
2527             IMPORT_GENERATED_ANNOTATION,
2528             "import javax.inject.Provider;",
2529             "",
2530             GENERATION_OPTIONS_ANNOTATION,
2531             GENERATED_ANNOTATION,
2532             "public abstract class DaggerLeaf implements Leaf {",
2533             "  protected DaggerLeaf() {}",
2534             "",
2535             "  @Override",
2536             "  public Provider<Map<Integer, Multibound>> map() {",
2537             "    return MapFactory.<Integer, Multibound>emptyMapProvider();",
2538             "  }",
2539             "}");
2540     Compilation compilation = compile(filesToCompile.build());
2541     assertThat(compilation).succeededWithoutWarnings();
2542     assertThat(compilation)
2543         .generatedSourceFile("test.DaggerLeaf")
2544         .hasSourceEquivalentTo(generatedLeaf);
2545 
2546     filesToCompile.add(
2547         JavaFileObjects.forSourceLines(
2548             "test.Ancestor",
2549             "package test;",
2550             "",
2551             "import dagger.Subcomponent;",
2552             "",
2553             "@Subcomponent(modules = AncestorModule.class)",
2554             "interface Ancestor {",
2555             "  Leaf leaf();",
2556             "}"),
2557         JavaFileObjects.forSourceLines(
2558             "test.AncestorModule",
2559             "package test;",
2560             "",
2561             "import dagger.Module;",
2562             "import dagger.Provides;",
2563             "import dagger.multibindings.IntKey;",
2564             "import dagger.multibindings.IntoMap;",
2565             "",
2566             "@Module",
2567             "class AncestorModule {",
2568             "  @Provides",
2569             "  @IntoMap",
2570             "  @IntKey(111)",
2571             "  static Multibound fromAncestor() {",
2572             "    return new Multibound();",
2573             "  }",
2574             "}"));
2575     JavaFileObject generatedAncestor =
2576         JavaFileObjects.forSourceLines(
2577             "test.DaggerAncestor",
2578             "package test;",
2579             "",
2580             "import dagger.internal.DelegateFactory;",
2581             "import dagger.internal.GenerationOptions;",
2582             "import dagger.internal.MapFactory;",
2583             "import java.util.Map;",
2584             IMPORT_GENERATED_ANNOTATION,
2585             "import javax.inject.Provider;",
2586             "",
2587             GENERATION_OPTIONS_ANNOTATION,
2588             GENERATED_ANNOTATION,
2589             "public abstract class DaggerAncestor implements Ancestor {",
2590             "  protected DaggerAncestor() {}",
2591             "",
2592             "  protected abstract class LeafImpl extends DaggerLeaf {",
2593             "    private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider =",
2594             "        new DelegateFactory<>()",
2595             "",
2596             "    protected LeafImpl() {}",
2597             "",
2598             "    protected void configureInitialization() {",
2599             "      initialize();",
2600             "    }",
2601             "",
2602             "    @SuppressWarnings(\"unchecked\")",
2603             "    private void initialize() {",
2604             "      DelegateFactory.setDelegate(",
2605             "          mapOfIntegerAndMultiboundProvider,",
2606             "          MapFactory.<Integer, Multibound>builder(1)",
2607             "              .put(111, AncestorModule_FromAncestorFactory.create())",
2608             "              .build());",
2609             "    }",
2610             "",
2611             "    @Override",
2612             "    public Provider<Map<Integer, Multibound>> map() {",
2613             "      return mapOfIntegerAndMultiboundProvider;",
2614             "    }",
2615             "  }",
2616             "}");
2617     compilation = compile(filesToCompile.build());
2618     assertThat(compilation).succeededWithoutWarnings();
2619     assertThat(compilation)
2620         .generatedSourceFile("test.DaggerAncestor")
2621         .hasSourceEquivalentTo(generatedAncestor);
2622   }
2623 
2624   @Test
bindsMissingDep_Multibindings()2625   public void bindsMissingDep_Multibindings() {
2626     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2627     filesToCompile.add(
2628         JavaFileObjects.forSourceLines(
2629             "test.LeafModule",
2630             "package test;",
2631             "",
2632             "import dagger.Binds;",
2633             "import dagger.Module;",
2634             "import dagger.multibindings.IntoSet;",
2635             "",
2636             "@Module",
2637             "interface LeafModule {",
2638             "  @Binds",
2639             "  @IntoSet",
2640             "  CharSequence bindsMultibindingWithMissingDep(String string);",
2641             "}"),
2642         JavaFileObjects.forSourceLines(
2643             "test.Leaf",
2644             "package test;",
2645             "",
2646             "import dagger.Subcomponent;",
2647             "import java.util.Set;",
2648             "",
2649             "@Subcomponent(modules = LeafModule.class)",
2650             "interface Leaf {",
2651             "  Set<CharSequence> set();",
2652             "}"));
2653 
2654     JavaFileObject generatedLeaf =
2655         JavaFileObjects.forSourceLines(
2656             "test.DaggerLeaf",
2657             "package test;",
2658             "",
2659             "import com.google.common.collect.ImmutableSet;",
2660             "import dagger.internal.GenerationOptions;",
2661             "import java.util.Set;",
2662             IMPORT_GENERATED_ANNOTATION,
2663             "",
2664             GENERATION_OPTIONS_ANNOTATION,
2665             GENERATED_ANNOTATION,
2666             "public abstract class DaggerLeaf implements Leaf {",
2667             "  protected DaggerLeaf() {}",
2668             "",
2669             "  @Override",
2670             "  public Set<CharSequence> set() {",
2671             "    return ImmutableSet.<CharSequence>of(getBindsMultibindingWithMissingDep());",
2672             "  }",
2673             "",
2674             // The expected output here is subtle: the Key of
2675             // LeafModule.bindsMultibindingWithMissingDep() is Set<CharSequence>, but the binding
2676             // method should only be returning an individual CharSequence. Otherwise the
2677             // ImmutableSet factory method above will fail.
2678             "  protected abstract CharSequence getBindsMultibindingWithMissingDep();",
2679             "}");
2680     Compilation compilation = compile(filesToCompile.build());
2681     assertThat(compilation).succeededWithoutWarnings();
2682     assertThat(compilation)
2683         .generatedSourceFile("test.DaggerLeaf")
2684         .hasSourceEquivalentTo(generatedLeaf);
2685   }
2686 
2687   @Test
multibindingsAndFastInit()2688   public void multibindingsAndFastInit() {
2689     ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
2690     createSimplePackagePrivateClasses(filesToCompile, "PackagePrivate");
2691     filesToCompile.add(
2692         JavaFileObjects.forSourceLines(
2693             "test.MultibindingModule",
2694             "package test;",
2695             "",
2696             "import dagger.Module;",
2697             "import dagger.Provides;",
2698             "import dagger.multibindings.IntKey;",
2699             "import dagger.multibindings.IntoMap;",
2700             "import dagger.multibindings.IntoSet;",
2701             "",
2702             "@Module",
2703             "interface MultibindingModule {",
2704             "  @Provides",
2705             "  @IntoSet",
2706             "  @LeafScope",
2707             "  static PackagePrivate setContribution() {",
2708             "    return new PackagePrivate();",
2709             "  }",
2710             "",
2711             "  @Provides",
2712             "  @IntoMap",
2713             "  @IntKey(1)",
2714             "  @LeafScope",
2715             "  static PackagePrivate mapContribution() {",
2716             "    return new PackagePrivate();",
2717             "  }",
2718             "}"),
2719         JavaFileObjects.forSourceLines(
2720             "test.LeafScope",
2721             "package test;",
2722             "",
2723             "import javax.inject.Scope;",
2724             "",
2725             "@Scope",
2726             "@interface LeafScope {}"),
2727         JavaFileObjects.forSourceLines(
2728             "test.UsesMultibindings",
2729             "package test;",
2730             "",
2731             "import java.util.Map;",
2732             "import java.util.Set;",
2733             "import javax.inject.Inject;",
2734             "",
2735             "class UsesMultibindings {",
2736             "  @Inject",
2737             "  UsesMultibindings(Set<PackagePrivate> set, Map<Integer, PackagePrivate> map) {}",
2738             "}"),
2739         JavaFileObjects.forSourceLines(
2740             "test.Leaf",
2741             "package test;",
2742             "",
2743             "import dagger.Subcomponent;",
2744             "import java.util.Map;",
2745             "import java.util.Set;",
2746             "",
2747             "@LeafScope",
2748             "@Subcomponent(modules = MultibindingModule.class)",
2749             "interface Leaf {",
2750             "  UsesMultibindings entryPoint();",
2751             "}"));
2752 
2753     Compilation compilation =
2754         compilerWithOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE, FAST_INIT_MODE)
2755             .compile(filesToCompile.build());
2756     assertThat(compilation).succeededWithoutWarnings();
2757 
2758     JavaFileObject generatedLeaf =
2759         JavaFileObjects.forSourceLines(
2760             "test.DaggerLeaf",
2761             "package test;",
2762             "",
2763             "@GenerationOptions(fastInit = true)",
2764             GENERATED_ANNOTATION,
2765             "public abstract class DaggerLeaf implements Leaf {",
2766             "  protected DaggerLeaf() {}",
2767             "",
2768             "  private PackagePrivate getSetContribution() {",
2769             "    Object local = setContribution;",
2770             "    if (local instanceof MemoizedSentinel) {",
2771             "      synchronized (local) {",
2772             "        local = setContribution;",
2773             "        if (local instanceof MemoizedSentinel) {",
2774             "          local = MultibindingModule_SetContributionFactory.setContribution();",
2775             "          setContribution = DoubleCheck.reentrantCheck(setContribution, local);",
2776             "        }",
2777             "      }",
2778             "    }",
2779             "    return (PackagePrivate) local;",
2780             "  }",
2781             "",
2782             "  private PackagePrivate getMapContribution() {",
2783             "    Object local = mapContribution;",
2784             "    if (local instanceof MemoizedSentinel) {",
2785             "      synchronized (local) {",
2786             "        local = mapContribution;",
2787             "        if (local instanceof MemoizedSentinel) {",
2788             "          local = MultibindingModule_MapContributionFactory.mapContribution();",
2789             "          mapContribution = DoubleCheck.reentrantCheck(mapContribution, local);",
2790             "        }",
2791             "      }",
2792             "    }",
2793             "    return (PackagePrivate) local;",
2794             "  }",
2795             "",
2796             "  @Override",
2797             "  public UsesMultibindings entryPoint() {",
2798             "    return new UsesMultibindings(",
2799             "        getSetOfPackagePrivate(), getMapOfIntegerAndPackagePrivate());",
2800             "  }",
2801             "",
2802             "  protected Set getSetOfPackagePrivate() {",
2803             "    return ImmutableSet.<PackagePrivate>of(getSetContribution());",
2804             "  }",
2805             "",
2806             "  protected Map getMapOfIntegerAndPackagePrivate() {",
2807             "    return ImmutableMap.<Integer, PackagePrivate>of(1, getMapContribution());",
2808             "  }",
2809             "}");
2810     assertThat(compilation)
2811         .generatedSourceFile("test.DaggerLeaf")
2812         .containsElementsIn(generatedLeaf);
2813   }
2814 
2815   // TODO(ronshapiro): remove copies from AheadOfTimeSubcomponents*Test classes
createSimplePackagePrivateClasses( ImmutableList.Builder<JavaFileObject> filesBuilder, String... ancillaryClasses)2816   private void createSimplePackagePrivateClasses(
2817       ImmutableList.Builder<JavaFileObject> filesBuilder, String... ancillaryClasses) {
2818     for (String className : ancillaryClasses) {
2819       filesBuilder.add(
2820           JavaFileObjects.forSourceLines(
2821               String.format("test.%s", className),
2822               "package test;",
2823               "",
2824               String.format("class %s { }", className)));
2825     }
2826   }
2827 
compile(Iterable<JavaFileObject> files)2828   private static Compilation compile(Iterable<JavaFileObject> files) {
2829     return compilerWithOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE).compile(files);
2830   }
2831 
compileWithoutGuava(Iterable<JavaFileObject> files)2832   private static Compilation compileWithoutGuava(Iterable<JavaFileObject> files) {
2833     return daggerCompiler()
2834         .withOptions(
2835             AHEAD_OF_TIME_SUBCOMPONENTS_MODE.javacopts().append(CLASS_PATH_WITHOUT_GUAVA_OPTION))
2836         .compile(files);
2837   }
2838 }
2839