xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/SubcomponentValidationTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2015 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 androidx.room.compiler.processing.util.Source;
20 import com.squareup.javapoet.MethodSpec;
21 import com.squareup.javapoet.TypeSpec;
22 import dagger.internal.codegen.javapoet.TypeNames;
23 import dagger.testing.compile.CompilerTests;
24 import dagger.testing.golden.GoldenFileRule;
25 import java.util.Collection;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.junit.runners.Parameterized;
30 import org.junit.runners.Parameterized.Parameters;
31 
32 @RunWith(Parameterized.class)
33 public class SubcomponentValidationTest {
34   @Parameters(name = "{0}")
parameters()35   public static Collection<Object[]> parameters() {
36     return CompilerMode.TEST_PARAMETERS;
37   }
38 
39   private final CompilerMode compilerMode;
40 
SubcomponentValidationTest(CompilerMode compilerMode)41   public SubcomponentValidationTest(CompilerMode compilerMode) {
42     this.compilerMode = compilerMode;
43   }
44 
45   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
46 
factoryMethod_missingModulesWithParameters()47   @Test public void factoryMethod_missingModulesWithParameters() {
48     Source componentFile =
49         CompilerTests.javaSource(
50             "test.TestComponent",
51             "package test;",
52             "",
53             "import dagger.Component;",
54             "",
55             "@Component",
56             "interface TestComponent {",
57             "  ChildComponent newChildComponent();",
58             "}");
59     Source childComponentFile =
60         CompilerTests.javaSource(
61             "test.ChildComponent",
62             "package test;",
63             "",
64             "import dagger.Subcomponent;",
65             "",
66             "@Subcomponent(modules = ModuleWithParameters.class)",
67             "interface ChildComponent {",
68             "  Object object();",
69             "}");
70     Source moduleFile =
71         CompilerTests.javaSource(
72             "test.ModuleWithParameters",
73             "package test;",
74             "",
75             "import dagger.Module;",
76             "import dagger.Provides;",
77             "",
78             "@Module",
79             "final class ModuleWithParameters {",
80             "  private final Object object;",
81             "",
82             "  ModuleWithParameters(Object object) {",
83             "    this.object = object;",
84             "  }",
85             "",
86             "  @Provides Object object() {",
87             "    return object;",
88             "  }",
89             "}");
90     CompilerTests.daggerCompiler(componentFile, childComponentFile, moduleFile)
91         .withProcessingOptions(compilerMode.processorOptions())
92         .compile(
93             subject -> {
94               subject.hasErrorCount(1);
95               subject.hasErrorContaining(
96                       "test.ChildComponent requires modules which have no visible default "
97                           + "constructors. Add the following modules as parameters to this method: "
98                           + "test.ModuleWithParameters")
99                   .onSource(componentFile)
100                   .onLineContaining("ChildComponent newChildComponent();");
101             });
102   }
103 
104   @Test
factoryMethod_grandchild()105   public void factoryMethod_grandchild() {
106     Source component =
107         CompilerTests.javaSource(
108             "test.TestComponent",
109             "package test;",
110             "",
111             "import dagger.Component;",
112             "",
113             "@Component",
114             "interface TestComponent {",
115             "  ChildComponent newChildComponent();",
116             "}");
117     Source childComponent =
118         CompilerTests.javaSource(
119             "test.ChildComponent",
120             "package test;",
121             "",
122             "import dagger.Subcomponent;",
123             "",
124             "@Subcomponent",
125             "interface ChildComponent {",
126             "  GrandchildComponent newGrandchildComponent();",
127             "}");
128     Source grandchildComponent =
129         CompilerTests.javaSource(
130             "test.GrandchildComponent",
131             "package test;",
132             "",
133             "import dagger.Subcomponent;",
134             "",
135             "@Subcomponent(modules = GrandchildModule.class)",
136             "interface GrandchildComponent {",
137             "  Object object();",
138             "}");
139     Source grandchildModule =
140         CompilerTests.javaSource(
141             "test.GrandchildModule",
142             "package test;",
143             "",
144             "import dagger.Module;",
145             "import dagger.Provides;",
146             "",
147             "@Module",
148             "final class GrandchildModule {",
149             "  private final Object object;",
150             "",
151             "  GrandchildModule(Object object) {",
152             "    this.object = object;",
153             "  }",
154             "",
155             "  @Provides Object object() {",
156             "    return object;",
157             "  }",
158             "}");
159     CompilerTests.daggerCompiler(component, childComponent, grandchildComponent, grandchildModule)
160         .withProcessingOptions(compilerMode.processorOptions())
161         .compile(
162             subject -> {
163               subject.hasErrorCount(1);
164               subject.hasErrorContaining(
165                       "[ChildComponent.newGrandchildComponent()] "
166                           + "GrandchildComponent requires modules which have no visible default "
167                           + "constructors. Add the following modules as parameters to this method: "
168                           + "GrandchildModule")
169                   .onSource(component)
170                   .onLineContaining("interface TestComponent");
171             });
172   }
173 
factoryMethod_nonModuleParameter()174   @Test public void factoryMethod_nonModuleParameter() {
175     Source componentFile =
176         CompilerTests.javaSource("test.TestComponent",
177         "package test;",
178         "",
179         "import dagger.Component;",
180         "",
181         "@Component",
182         "interface TestComponent {",
183         "  ChildComponent newChildComponent(String someRandomString);",
184         "}");
185     Source childComponentFile =
186         CompilerTests.javaSource("test.ChildComponent",
187         "package test;",
188         "",
189         "import dagger.Subcomponent;",
190         "",
191         "@Subcomponent",
192         "interface ChildComponent {}");
193     CompilerTests.daggerCompiler(componentFile, childComponentFile)
194         .withProcessingOptions(compilerMode.processorOptions())
195         .compile(
196             subject -> {
197               subject.hasErrorCount(1);
198               subject.hasErrorContaining(
199                       "Subcomponent factory methods may only accept modules, but java.lang.String "
200                           + "is not.")
201                   .onSource(componentFile)
202                   .onLine(7);
203             });
204   }
205 
factoryMethod_duplicateParameter()206   @Test public void factoryMethod_duplicateParameter() {
207     Source moduleFile =
208         CompilerTests.javaSource("test.TestModule",
209         "package test;",
210         "",
211         "import dagger.Module;",
212         "",
213         "@Module",
214         "final class TestModule {}");
215     Source componentFile =
216         CompilerTests.javaSource("test.TestComponent",
217         "package test;",
218         "",
219         "import dagger.Component;",
220         "",
221         "@Component",
222         "interface TestComponent {",
223         "  ChildComponent newChildComponent(TestModule testModule1, TestModule testModule2);",
224         "}");
225     Source childComponentFile =
226         CompilerTests.javaSource("test.ChildComponent",
227         "package test;",
228         "",
229         "import dagger.Subcomponent;",
230         "",
231         "@Subcomponent(modules = TestModule.class)",
232         "interface ChildComponent {}");
233     CompilerTests.daggerCompiler(componentFile, childComponentFile, moduleFile)
234         .withProcessingOptions(compilerMode.processorOptions())
235         .compile(
236             subject -> {
237               subject.hasErrorCount(1);
238               subject.hasErrorContaining(
239                       "A module may only occur once as an argument in a Subcomponent factory "
240                           + "method, but test.TestModule was already passed.")
241                   .onSource(componentFile)
242                   .onLine(7);
243             });
244   }
245 
factoryMethod_superflouousModule()246   @Test public void factoryMethod_superflouousModule() {
247     Source moduleFile =
248         CompilerTests.javaSource("test.TestModule",
249         "package test;",
250         "",
251         "import dagger.Module;",
252         "",
253         "@Module",
254         "final class TestModule {}");
255     Source componentFile =
256         CompilerTests.javaSource("test.TestComponent",
257         "package test;",
258         "",
259         "import dagger.Component;",
260         "",
261         "@Component",
262         "interface TestComponent {",
263         "  ChildComponent newChildComponent(TestModule testModule);",
264         "}");
265     Source childComponentFile =
266         CompilerTests.javaSource("test.ChildComponent",
267         "package test;",
268         "",
269         "import dagger.Subcomponent;",
270         "",
271         "@Subcomponent",
272         "interface ChildComponent {}");
273     CompilerTests.daggerCompiler(moduleFile, componentFile, childComponentFile)
274         .withProcessingOptions(compilerMode.processorOptions())
275         .compile(
276             subject -> {
277               subject.hasErrorCount(1);
278               subject.hasErrorContaining(
279                       "test.TestModule is present as an argument to the test.ChildComponent "
280                           + "factory method, but is not one of the modules used to implement the "
281                           + "subcomponent.")
282                   .onSource(componentFile)
283                   .onLine(7);
284             });
285   }
286 
missingBinding()287   @Test public void missingBinding() {
288     Source moduleFile =
289         CompilerTests.javaSource("test.TestModule",
290         "package test;",
291         "",
292         "import dagger.Module;",
293         "import dagger.Provides;",
294         "",
295         "@Module",
296         "final class TestModule {",
297         "  @Provides String provideString(int i) {",
298         "    return Integer.toString(i);",
299         "  }",
300         "}");
301     Source componentFile =
302         CompilerTests.javaSource("test.TestComponent",
303         "package test;",
304         "",
305         "import dagger.Component;",
306         "",
307         "@Component",
308         "interface TestComponent {",
309         "  ChildComponent newChildComponent();",
310         "}");
311     Source childComponentFile =
312         CompilerTests.javaSource("test.ChildComponent",
313         "package test;",
314         "",
315         "import dagger.Subcomponent;",
316         "",
317         "@Subcomponent(modules = TestModule.class)",
318         "interface ChildComponent {",
319         "  String string();",
320         "}");
321     CompilerTests.daggerCompiler(moduleFile, componentFile, childComponentFile)
322         .withProcessingOptions(compilerMode.processorOptions())
323         .compile(
324             subject -> {
325               subject.hasErrorCount(1);
326               subject.hasErrorContaining(
327                       "Integer cannot be provided without an @Inject constructor or an "
328                           + "@Provides-annotated method")
329                   .onSource(componentFile)
330                   .onLineContaining("interface TestComponent");
331             });
332   }
333 
subcomponentOnConcreteType()334   @Test public void subcomponentOnConcreteType() {
335     Source subcomponentFile =
336         CompilerTests.javaSource("test.NotASubcomponent",
337         "package test;",
338         "",
339         "import dagger.Subcomponent;",
340         "",
341         "@Subcomponent",
342         "final class NotASubcomponent {}");
343     CompilerTests.daggerCompiler(subcomponentFile)
344         .withProcessingOptions(compilerMode.processorOptions())
345         .compile(
346             subject -> {
347               subject.hasErrorCount(1);
348               subject.hasErrorContaining("interface");
349             });
350   }
351 
scopeMismatch()352   @Test public void scopeMismatch() {
353     Source componentFile =
354         CompilerTests.javaSource("test.ParentComponent",
355         "package test;",
356         "",
357         "import dagger.Component;",
358         "import javax.inject.Singleton;",
359         "",
360         "@Component",
361         "@Singleton",
362         "interface ParentComponent {",
363         "  ChildComponent childComponent();",
364         "}");
365     Source subcomponentFile =
366         CompilerTests.javaSource("test.ChildComponent",
367         "package test;",
368         "",
369         "import dagger.Subcomponent;",
370         "",
371         "@Subcomponent(modules = ChildModule.class)",
372         "interface ChildComponent {",
373         "  Object object();",
374         "}");
375     Source moduleFile =
376         CompilerTests.javaSource("test.ChildModule",
377         "package test;",
378         "",
379         "import dagger.Module;",
380         "import dagger.Provides;",
381         "import javax.inject.Singleton;",
382         "",
383         "@Module",
384         "final class ChildModule {",
385         "  @Provides @Singleton Object provideObject() { return null; }",
386         "}");
387     CompilerTests.daggerCompiler(componentFile, subcomponentFile, moduleFile)
388         .withProcessingOptions(compilerMode.processorOptions())
389         .compile(
390             subject -> {
391               subject.hasErrorCount(1);
392               subject.hasErrorContaining("@Singleton");
393             });
394   }
395 
396   @Test
delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent()397   public void delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent()
398       throws Exception {
399     Source parentComponentFile =
400         CompilerTests.javaSource(
401             "test.ParentComponent",
402             "package test;",
403             "",
404             "import dagger.Component;",
405             "import javax.inject.Singleton;",
406             "",
407             "@Singleton",
408             "@Component",
409             "interface ParentComponent {",
410             "  ChildComponent childComponent();",
411             "  Dep1 dep1();",
412             "  Dep2 dep2();",
413             "}");
414     Source childComponentFile =
415         CompilerTests.javaSource(
416             "test.ChildComponent",
417             "package test;",
418             "",
419             "import dagger.Subcomponent;",
420             "",
421             "@Subcomponent(modules = ChildModule.class)",
422             "interface ChildComponent {",
423             "  Object object();",
424             "}");
425     Source childModuleFile =
426         CompilerTests.javaSource(
427             "test.ChildModule",
428             "package test;",
429             "",
430             "import dagger.Module;",
431             "import dagger.Provides;",
432             "",
433             "@Module",
434             "final class ChildModule {",
435             "  @Provides Object provideObject(A a) { return null; }",
436             "}");
437     Source aFile =
438         CompilerTests.javaSource(
439             "test.A",
440             "package test;",
441             "",
442             "import javax.inject.Inject;",
443             "",
444             "final class A {",
445             "  @Inject public A(NeedsDep1 a, Dep1 b, Dep2 c) { }",
446             "  @Inject public void methodA() { }",
447             "}");
448     Source needsDep1File =
449         CompilerTests.javaSource(
450             "test.NeedsDep1",
451             "package test;",
452             "",
453             "import javax.inject.Inject;",
454             "",
455             "final class NeedsDep1 {",
456             "  @Inject public NeedsDep1(Dep1 d) { }",
457             "}");
458     Source dep1File =
459         CompilerTests.javaSource(
460             "test.Dep1",
461             "package test;",
462             "",
463             "import javax.inject.Inject;",
464             "import javax.inject.Singleton;",
465             "",
466             "@Singleton",
467             "final class Dep1 {",
468             "  @Inject public Dep1() { }",
469             "  @Inject public void dep1Method() { }",
470             "}");
471     Source dep2File =
472         CompilerTests.javaSource(
473             "test.Dep2",
474             "package test;",
475             "",
476             "import javax.inject.Inject;",
477             "import javax.inject.Singleton;",
478             "",
479             "@Singleton",
480             "final class Dep2 {",
481             "  @Inject public Dep2() { }",
482             "  @Inject public void dep2Method() { }",
483             "}");
484 
485     CompilerTests.daggerCompiler(
486             parentComponentFile,
487             childComponentFile,
488             childModuleFile,
489             aFile,
490             needsDep1File,
491             dep1File,
492             dep2File)
493         .withProcessingOptions(compilerMode.processorOptions())
494         .compile(
495             subject -> {
496               subject.hasErrorCount(0);
497               subject.generatedSource(
498                   goldenFileRule.goldenSource("test/DaggerParentComponent"));
499             });
500   }
501 
502   @Test
multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent()503   public void multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent() throws Exception {
504     Source parent =
505         CompilerTests.javaSource(
506             "test.ParentComponent",
507             "package test;",
508             "",
509             "import dagger.Component;",
510             "",
511             "@Component",
512             "interface ParentComponent {",
513             "  Foo.Sub newInstanceSubcomponent();",
514             "  NoConflict newNoConflictSubcomponent();",
515             "}");
516     Source foo =
517         CompilerTests.javaSource(
518             "test.Foo",
519             "package test;",
520             "",
521             "import dagger.Subcomponent;",
522             "",
523             "interface Foo {",
524             "  @Subcomponent interface Sub {",
525             "    Bar.Sub newBarSubcomponent();",
526             "  }",
527             "}");
528     Source bar =
529         CompilerTests.javaSource(
530             "test.Bar",
531             "package test;",
532             "",
533             "import dagger.Subcomponent;",
534             "",
535             "interface Bar {",
536             "  @Subcomponent interface Sub {",
537             "    test.subpackage.Sub newSubcomponentInSubpackage();",
538             "  }",
539             "}");
540     Source baz =
541         CompilerTests.javaSource(
542             "test.subpackage.Sub",
543             "package test.subpackage;",
544             "",
545             "import dagger.Subcomponent;",
546             "",
547             "@Subcomponent public interface Sub {}");
548     Source noConflict =
549         CompilerTests.javaSource(
550             "test.NoConflict",
551             "package test;",
552             "",
553             "import dagger.Subcomponent;",
554             "",
555             "@Subcomponent interface NoConflict {}");
556 
557     CompilerTests.daggerCompiler(parent, foo, bar, baz, noConflict)
558         .withProcessingOptions(compilerMode.processorOptions())
559         .compile(
560             subject -> {
561               subject.hasErrorCount(0);
562               subject.generatedSource(
563                   goldenFileRule.goldenSource("test/DaggerParentComponent"));
564             });
565   }
566 
567   @Test
subcomponentSimpleNamesDisambiguated()568   public void subcomponentSimpleNamesDisambiguated() throws Exception {
569     Source parent =
570         CompilerTests.javaSource(
571             "test.ParentComponent",
572             "package test;",
573             "",
574             "import dagger.Component;",
575             "",
576             "@Component",
577             "interface ParentComponent {",
578             "  Sub newSubcomponent();",
579             "}");
580     Source sub =
581         CompilerTests.javaSource(
582             "test.Sub",
583             "package test;",
584             "",
585             "import dagger.Subcomponent;",
586             "",
587             "@Subcomponent interface Sub {",
588             "  test.deep.many.levels.that.match.test.Sub newDeepSubcomponent();",
589             "}");
590     Source deepSub =
591         CompilerTests.javaSource(
592             "test.deep.many.levels.that.match.test.Sub",
593             "package test.deep.many.levels.that.match.test;",
594             "",
595             "import dagger.Subcomponent;",
596             "",
597             "@Subcomponent public interface Sub {}");
598 
599     CompilerTests.daggerCompiler(parent, sub, deepSub)
600         .withProcessingOptions(compilerMode.processorOptions())
601         .compile(
602             subject -> {
603               subject.hasErrorCount(0);
604               subject.generatedSource(
605                   goldenFileRule.goldenSource("test/DaggerParentComponent"));
606             });
607   }
608 
609   @Test
subcomponentSimpleNamesDisambiguatedInRoot()610   public void subcomponentSimpleNamesDisambiguatedInRoot() throws Exception {
611     Source parent =
612         CompilerTests.javaSource(
613             "ParentComponent",
614             "import dagger.Component;",
615             "",
616             "@Component",
617             "interface ParentComponent {",
618             "  Sub newSubcomponent();",
619             "}");
620     Source sub =
621         CompilerTests.javaSource(
622             "Sub",
623             "import dagger.Subcomponent;",
624             "",
625             "@Subcomponent interface Sub {",
626             "  test.deep.many.levels.that.match.test.Sub newDeepSubcomponent();",
627             "}");
628     Source deepSub =
629         CompilerTests.javaSource(
630             "test.deep.many.levels.that.match.test.Sub",
631             "package test.deep.many.levels.that.match.test;",
632             "",
633             "import dagger.Subcomponent;",
634             "",
635             "@Subcomponent public interface Sub {}");
636 
637     CompilerTests.daggerCompiler(parent, sub, deepSub)
638         .withProcessingOptions(compilerMode.processorOptions())
639         .compile(
640             subject -> {
641               subject.hasErrorCount(0);
642               subject.generatedSource(
643                   goldenFileRule.goldenSource("DaggerParentComponent"));
644             });
645   }
646 
647   @Test
subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary()648   public void subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary() throws Exception {
649     Source parent =
650         CompilerTests.javaSource(
651             "test.ParentComponent",
652             "package test;",
653             "",
654             "import dagger.Component;",
655             "",
656             "@Component",
657             "interface ParentComponent {",
658             "  top1.a.b.c.d.E.F.Sub top1();",
659             "  top2.a.b.c.d.E.F.Sub top2();",
660             "}");
661     Source top1 =
662         CompilerTests.javaSource(
663             "top1.a.b.c.d.E",
664             "package top1.a.b.c.d;",
665             "",
666             "import dagger.Subcomponent;",
667             "",
668             "public interface E {",
669             "  interface F {",
670             "    @Subcomponent interface Sub {}",
671             "  }",
672             "}");
673     Source top2 =
674         CompilerTests.javaSource(
675             "top2.a.b.c.d.E",
676             "package top2.a.b.c.d;",
677             "",
678             "import dagger.Subcomponent;",
679             "",
680             "public interface E {",
681             "  interface F {",
682             "    @Subcomponent interface Sub {}",
683             "  }",
684             "}");
685 
686     CompilerTests.daggerCompiler(parent, top1, top2)
687         .withProcessingOptions(compilerMode.processorOptions())
688         .compile(
689             subject -> {
690               subject.hasErrorCount(0);
691               subject.generatedSource(
692                   goldenFileRule.goldenSource("test/DaggerParentComponent"));
693             });
694   }
695 
696   @Test
subcomponentNamesShouldNotConflictWithParent()697   public void subcomponentNamesShouldNotConflictWithParent()
698       throws Exception {
699     Source parent =
700         CompilerTests.javaSource(
701             "test.C",
702             "package test;",
703             "",
704             "import dagger.Component;",
705             "",
706             "@Component",
707             "interface C {",
708             "  test.Foo.C newInstanceC();",
709             "}");
710     Source subcomponentWithSameSimpleNameAsParent =
711         CompilerTests.javaSource(
712             "test.Foo",
713             "package test;",
714             "",
715             "import dagger.Subcomponent;",
716             "",
717             "interface Foo {",
718             "  @Subcomponent interface C {}",
719             "}");
720 
721     CompilerTests.daggerCompiler(parent, subcomponentWithSameSimpleNameAsParent)
722         .withProcessingOptions(compilerMode.processorOptions())
723         .compile(
724             subject -> {
725               subject.hasErrorCount(0);
726               subject.generatedSource(
727                   goldenFileRule.goldenSource("test/DaggerC"));
728             });
729   }
730 
731   @Test
subcomponentBuilderNamesShouldNotConflict()732   public void subcomponentBuilderNamesShouldNotConflict() throws Exception {
733     Source parent =
734         CompilerTests.javaSource(
735             "test.C",
736             "package test;",
737             "",
738             "import dagger.Component;",
739             "import dagger.Subcomponent;",
740             "",
741             "@Component",
742             "interface C {",
743             "  Foo.Sub.Builder fooBuilder();",
744             "  Bar.Sub.Builder barBuilder();",
745             "",
746             "  interface Foo {",
747             "    @Subcomponent",
748             "    interface Sub {",
749             "      @Subcomponent.Builder",
750             "      interface Builder {",
751             "        Sub build();",
752             "      }",
753             "    }",
754             "  }",
755             "",
756             "  interface Bar {",
757             "    @Subcomponent",
758             "    interface Sub {",
759             "      @Subcomponent.Builder",
760             "      interface Builder {",
761             "        Sub build();",
762             "      }",
763             "    }",
764             "  }",
765             "}");
766 
767     CompilerTests.daggerCompiler(parent)
768         .withProcessingOptions(compilerMode.processorOptions())
769         .compile(
770             subject -> {
771               subject.hasErrorCount(0);
772               subject.generatedSource(
773                   goldenFileRule.goldenSource("test/DaggerC"));
774             });
775   }
776 
777   @Test
duplicateBindingWithSubcomponentDeclaration()778   public void duplicateBindingWithSubcomponentDeclaration() {
779     Source module =
780         CompilerTests.javaSource(
781             "test.TestModule",
782             "package test;",
783             "",
784             "import dagger.Module;",
785             "import dagger.Provides;",
786             "",
787             "@Module(subcomponents = Sub.class)",
788             "class TestModule {",
789             "  @Provides Sub.Builder providesConflictsWithModuleSubcomponents() { return null; }",
790             "  @Provides Object usesSubcomponentBuilder(Sub.Builder builder) {",
791             "    return new Builder().toString();",
792             "  }",
793             "}");
794 
795     Source subcomponent =
796         CompilerTests.javaSource(
797             "test.Sub",
798             "package test;",
799             "",
800             "import dagger.Subcomponent;",
801             "",
802             "@Subcomponent",
803             "interface Sub {",
804             "  @Subcomponent.Builder",
805             "  interface Builder {",
806             "    Sub build();",
807             "  }",
808             "}");
809 
810     Source component =
811         CompilerTests.javaSource(
812             "test.C",
813             "package test;",
814             "",
815             "import dagger.Component;",
816             "",
817             "@Component(modules = TestModule.class)",
818             "interface C {",
819             "  Object dependsOnBuilder();",
820             "}");
821 
822     CompilerTests.daggerCompiler(module, component, subcomponent)
823         .withProcessingOptions(compilerMode.processorOptions())
824         .compile(
825             subject -> {
826               subject.hasErrorCount(1);
827               subject.hasErrorContaining("Sub.Builder is bound multiple times:");
828               subject.hasErrorContaining(
829                   "@Provides Sub.Builder TestModule.providesConflictsWithModuleSubcomponents()");
830               subject.hasErrorContaining("@Module(subcomponents = Sub.class) for TestModule");
831             });
832   }
833 
834   @Test
subcomponentDependsOnGeneratedType()835   public void subcomponentDependsOnGeneratedType() {
836     Source parent =
837         CompilerTests.javaSource(
838             "test.Parent",
839             "package test;",
840             "",
841             "import dagger.Component;",
842             "",
843             "@Component",
844             "interface Parent {",
845             "  Child.Builder childBuilder();",
846             "}");
847     Source child =
848         CompilerTests.javaSource(
849             "test.Child",
850             "package test;",
851             "",
852             "import dagger.Subcomponent;",
853             "",
854             "@Subcomponent",
855             "interface Child extends ChildSupertype {",
856             "  @Subcomponent.Builder",
857             "  interface Builder {",
858             "    Child build();",
859             "  }",
860             "}");
861     Source childSupertype =
862         CompilerTests.javaSource(
863             "test.ChildSupertype",
864             "package test;",
865             "",
866             "interface ChildSupertype {",
867             "  GeneratedInjectType generatedType();",
868             "}");
869     TypeSpec generatedInjectType =
870         TypeSpec.classBuilder("GeneratedInjectType")
871             .addMethod(
872                 MethodSpec.constructorBuilder()
873                     .addAnnotation(TypeNames.INJECT_JAVAX)
874                     .build())
875             .build();
876     CompilerTests.daggerCompiler(parent, child, childSupertype)
877         .withProcessingOptions(compilerMode.processorOptions())
878         .withProcessingSteps(() -> new GeneratingProcessingStep("test", generatedInjectType))
879         .compile(
880           subject -> {
881             subject.hasErrorCount(0);
882             subject.hasWarningCount(0);
883           });
884   }
885 }
886