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