xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/MissingBindingValidationTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
20*f585d8a3SJacky Wang 
21*f585d8a3SJacky Wang import androidx.room.compiler.processing.XProcessingEnv;
22*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.DiagnosticMessage;
23*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source;
24*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList;
25*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests;
26*f585d8a3SJacky Wang import java.util.List;
27*f585d8a3SJacky Wang import javax.tools.Diagnostic;
28*f585d8a3SJacky Wang import org.junit.Test;
29*f585d8a3SJacky Wang import org.junit.runner.RunWith;
30*f585d8a3SJacky Wang import org.junit.runners.Parameterized;
31*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters;
32*f585d8a3SJacky Wang 
33*f585d8a3SJacky Wang @RunWith(Parameterized.class)
34*f585d8a3SJacky Wang public class MissingBindingValidationTest {
35*f585d8a3SJacky Wang   @Parameters(name = "{0}")
parameters()36*f585d8a3SJacky Wang   public static ImmutableList<Object[]> parameters() {
37*f585d8a3SJacky Wang     return CompilerMode.TEST_PARAMETERS;
38*f585d8a3SJacky Wang   }
39*f585d8a3SJacky Wang 
40*f585d8a3SJacky Wang   private final CompilerMode compilerMode;
41*f585d8a3SJacky Wang 
MissingBindingValidationTest(CompilerMode compilerMode)42*f585d8a3SJacky Wang   public MissingBindingValidationTest(CompilerMode compilerMode) {
43*f585d8a3SJacky Wang     this.compilerMode = compilerMode;
44*f585d8a3SJacky Wang   }
45*f585d8a3SJacky Wang 
46*f585d8a3SJacky Wang   @Test
dependOnInterface()47*f585d8a3SJacky Wang   public void dependOnInterface() {
48*f585d8a3SJacky Wang     Source component =
49*f585d8a3SJacky Wang         CompilerTests.javaSource(
50*f585d8a3SJacky Wang             "test.MyComponent",
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 MyComponent {",
57*f585d8a3SJacky Wang             "  Foo getFoo();",
58*f585d8a3SJacky Wang             "}");
59*f585d8a3SJacky Wang     Source injectable =
60*f585d8a3SJacky Wang         CompilerTests.javaSource(
61*f585d8a3SJacky Wang             "test.Foo",
62*f585d8a3SJacky Wang             "package test;",
63*f585d8a3SJacky Wang             "",
64*f585d8a3SJacky Wang             "import javax.inject.Inject;",
65*f585d8a3SJacky Wang             "",
66*f585d8a3SJacky Wang             "class Foo {",
67*f585d8a3SJacky Wang             "  @Inject Foo(Bar bar) {}",
68*f585d8a3SJacky Wang             "}");
69*f585d8a3SJacky Wang     Source nonInjectable =
70*f585d8a3SJacky Wang         CompilerTests.javaSource(
71*f585d8a3SJacky Wang             "test.Bar",
72*f585d8a3SJacky Wang             "package test;",
73*f585d8a3SJacky Wang             "",
74*f585d8a3SJacky Wang             "import javax.inject.Inject;",
75*f585d8a3SJacky Wang             "",
76*f585d8a3SJacky Wang             "interface Bar {}");
77*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, injectable, nonInjectable)
78*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
79*f585d8a3SJacky Wang         .compile(
80*f585d8a3SJacky Wang             subject -> {
81*f585d8a3SJacky Wang               subject.hasErrorCount(1);
82*f585d8a3SJacky Wang               subject.hasErrorContaining(
83*f585d8a3SJacky Wang                       "Bar cannot be provided without an @Provides-annotated method.")
84*f585d8a3SJacky Wang                   .onSource(component)
85*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
86*f585d8a3SJacky Wang             });
87*f585d8a3SJacky Wang   }
88*f585d8a3SJacky Wang 
89*f585d8a3SJacky Wang   @Test
entryPointDependsOnInterface()90*f585d8a3SJacky Wang   public void entryPointDependsOnInterface() {
91*f585d8a3SJacky Wang     Source component =
92*f585d8a3SJacky Wang         CompilerTests.javaSource(
93*f585d8a3SJacky Wang             "test.TestClass",
94*f585d8a3SJacky Wang             "package test;",
95*f585d8a3SJacky Wang             "",
96*f585d8a3SJacky Wang             "import dagger.Component;",
97*f585d8a3SJacky Wang             "",
98*f585d8a3SJacky Wang             "final class TestClass {",
99*f585d8a3SJacky Wang             "  interface A {}",
100*f585d8a3SJacky Wang             "",
101*f585d8a3SJacky Wang             "  @Component()",
102*f585d8a3SJacky Wang             "  interface AComponent {",
103*f585d8a3SJacky Wang             "    A getA();",
104*f585d8a3SJacky Wang             "  }",
105*f585d8a3SJacky Wang             "}");
106*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
107*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
108*f585d8a3SJacky Wang         .compile(
109*f585d8a3SJacky Wang             subject -> {
110*f585d8a3SJacky Wang               subject.hasErrorCount(1);
111*f585d8a3SJacky Wang               subject.hasErrorContaining(
112*f585d8a3SJacky Wang                       "\033[1;31m[Dagger/MissingBinding]\033[0m TestClass.A cannot be provided "
113*f585d8a3SJacky Wang                           + "without an @Provides-annotated method.")
114*f585d8a3SJacky Wang                   .onSource(component)
115*f585d8a3SJacky Wang                   .onLineContaining("interface AComponent");
116*f585d8a3SJacky Wang             });
117*f585d8a3SJacky Wang   }
118*f585d8a3SJacky Wang 
119*f585d8a3SJacky Wang   @Test
entryPointDependsOnQualifiedInterface()120*f585d8a3SJacky Wang   public void entryPointDependsOnQualifiedInterface() {
121*f585d8a3SJacky Wang     Source component =
122*f585d8a3SJacky Wang         CompilerTests.javaSource(
123*f585d8a3SJacky Wang             "test.TestClass",
124*f585d8a3SJacky Wang             "package test;",
125*f585d8a3SJacky Wang             "",
126*f585d8a3SJacky Wang             "import dagger.Component;",
127*f585d8a3SJacky Wang             "import javax.inject.Qualifier;",
128*f585d8a3SJacky Wang             "",
129*f585d8a3SJacky Wang             "final class TestClass {",
130*f585d8a3SJacky Wang             "  @Qualifier @interface Q {}",
131*f585d8a3SJacky Wang             "  interface A {}",
132*f585d8a3SJacky Wang             "",
133*f585d8a3SJacky Wang             "  @Component()",
134*f585d8a3SJacky Wang             "  interface AComponent {",
135*f585d8a3SJacky Wang             "    @Q A qualifiedA();",
136*f585d8a3SJacky Wang             "  }",
137*f585d8a3SJacky Wang             "}");
138*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
139*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
140*f585d8a3SJacky Wang         .compile(
141*f585d8a3SJacky Wang             subject -> {
142*f585d8a3SJacky Wang               subject.hasErrorCount(1);
143*f585d8a3SJacky Wang               subject.hasErrorContaining(
144*f585d8a3SJacky Wang                       "\033[1;31m[Dagger/MissingBinding]\033[0m @TestClass.Q TestClass.A cannot be "
145*f585d8a3SJacky Wang                           + "provided without an @Provides-annotated method.")
146*f585d8a3SJacky Wang                   .onSource(component)
147*f585d8a3SJacky Wang                   .onLineContaining("interface AComponent");
148*f585d8a3SJacky Wang             });
149*f585d8a3SJacky Wang   }
150*f585d8a3SJacky Wang 
constructorInjectionWithoutAnnotation()151*f585d8a3SJacky Wang   @Test public void constructorInjectionWithoutAnnotation() {
152*f585d8a3SJacky Wang     Source component =
153*f585d8a3SJacky Wang         CompilerTests.javaSource("test.TestClass",
154*f585d8a3SJacky Wang         "package test;",
155*f585d8a3SJacky Wang         "",
156*f585d8a3SJacky Wang         "import dagger.Component;",
157*f585d8a3SJacky Wang         "import dagger.Module;",
158*f585d8a3SJacky Wang         "import dagger.Provides;",
159*f585d8a3SJacky Wang         "import javax.inject.Inject;",
160*f585d8a3SJacky Wang         "",
161*f585d8a3SJacky Wang         "final class TestClass {",
162*f585d8a3SJacky Wang         "  static class A {",
163*f585d8a3SJacky Wang         "    A() {}",
164*f585d8a3SJacky Wang         "  }",
165*f585d8a3SJacky Wang         "",
166*f585d8a3SJacky Wang         "  @Component()",
167*f585d8a3SJacky Wang         "  interface AComponent {",
168*f585d8a3SJacky Wang         "    A getA();",
169*f585d8a3SJacky Wang         "  }",
170*f585d8a3SJacky Wang         "}");
171*f585d8a3SJacky Wang 
172*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
173*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
174*f585d8a3SJacky Wang         .compile(
175*f585d8a3SJacky Wang             subject -> {
176*f585d8a3SJacky Wang               subject.hasErrorCount(1);
177*f585d8a3SJacky Wang               subject.hasErrorContaining(
178*f585d8a3SJacky Wang                       "TestClass.A cannot be provided without an @Inject constructor or an "
179*f585d8a3SJacky Wang                           + "@Provides-annotated method.")
180*f585d8a3SJacky Wang                   .onSource(component)
181*f585d8a3SJacky Wang                   .onLineContaining("interface AComponent");
182*f585d8a3SJacky Wang             });
183*f585d8a3SJacky Wang   }
184*f585d8a3SJacky Wang 
membersInjectWithoutProvision()185*f585d8a3SJacky Wang   @Test public void membersInjectWithoutProvision() {
186*f585d8a3SJacky Wang     Source component =
187*f585d8a3SJacky Wang         CompilerTests.javaSource(
188*f585d8a3SJacky Wang             "test.TestClass",
189*f585d8a3SJacky Wang             "package test;",
190*f585d8a3SJacky Wang             "",
191*f585d8a3SJacky Wang             "import dagger.Component;",
192*f585d8a3SJacky Wang             "import dagger.Module;",
193*f585d8a3SJacky Wang             "import dagger.Provides;",
194*f585d8a3SJacky Wang             "import javax.inject.Inject;",
195*f585d8a3SJacky Wang             "",
196*f585d8a3SJacky Wang             "final class TestClass {",
197*f585d8a3SJacky Wang             "  static class A {",
198*f585d8a3SJacky Wang             "    @Inject A() {}",
199*f585d8a3SJacky Wang             "  }",
200*f585d8a3SJacky Wang             "",
201*f585d8a3SJacky Wang             "  static class B {",
202*f585d8a3SJacky Wang             "    @Inject A a;",
203*f585d8a3SJacky Wang             "  }",
204*f585d8a3SJacky Wang             "",
205*f585d8a3SJacky Wang             "  @Component()",
206*f585d8a3SJacky Wang             "  interface AComponent {",
207*f585d8a3SJacky Wang             "    B getB();",
208*f585d8a3SJacky Wang             "  }",
209*f585d8a3SJacky Wang             "}");
210*f585d8a3SJacky Wang 
211*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
212*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
213*f585d8a3SJacky Wang         .compile(
214*f585d8a3SJacky Wang             subject -> {
215*f585d8a3SJacky Wang               subject.hasErrorCount(1);
216*f585d8a3SJacky Wang               subject.hasErrorContaining(
217*f585d8a3SJacky Wang                       "TestClass.B cannot be provided without an @Inject constructor or an "
218*f585d8a3SJacky Wang                           + "@Provides-annotated method. This type supports members injection but "
219*f585d8a3SJacky Wang                           + "cannot be implicitly provided.")
220*f585d8a3SJacky Wang                   .onSource(component)
221*f585d8a3SJacky Wang                   .onLineContaining("interface AComponent");
222*f585d8a3SJacky Wang             });
223*f585d8a3SJacky Wang   }
224*f585d8a3SJacky Wang 
225*f585d8a3SJacky Wang   @Test
missingBindingWithSameKeyAsMembersInjectionMethod()226*f585d8a3SJacky Wang   public void missingBindingWithSameKeyAsMembersInjectionMethod() {
227*f585d8a3SJacky Wang     Source self =
228*f585d8a3SJacky Wang         CompilerTests.javaSource(
229*f585d8a3SJacky Wang             "test.Self",
230*f585d8a3SJacky Wang             "package test;",
231*f585d8a3SJacky Wang             "",
232*f585d8a3SJacky Wang             "import javax.inject.Inject;",
233*f585d8a3SJacky Wang             "import javax.inject.Provider;",
234*f585d8a3SJacky Wang             "",
235*f585d8a3SJacky Wang             "class Self {",
236*f585d8a3SJacky Wang             "  @Inject Provider<Self> selfProvider;",
237*f585d8a3SJacky Wang             "}");
238*f585d8a3SJacky Wang     Source component =
239*f585d8a3SJacky Wang         CompilerTests.javaSource(
240*f585d8a3SJacky Wang             "test.SelfComponent",
241*f585d8a3SJacky Wang             "package test;",
242*f585d8a3SJacky Wang             "",
243*f585d8a3SJacky Wang             "import dagger.Component;",
244*f585d8a3SJacky Wang             "",
245*f585d8a3SJacky Wang             "@Component",
246*f585d8a3SJacky Wang             "interface SelfComponent {",
247*f585d8a3SJacky Wang             "  void inject(Self target);",
248*f585d8a3SJacky Wang             "}");
249*f585d8a3SJacky Wang 
250*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(self, component)
251*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
252*f585d8a3SJacky Wang         .compile(
253*f585d8a3SJacky Wang             subject -> {
254*f585d8a3SJacky Wang               subject.hasErrorCount(1);
255*f585d8a3SJacky Wang               subject.hasErrorContaining("Self cannot be provided without an @Inject constructor")
256*f585d8a3SJacky Wang                   .onSource(component)
257*f585d8a3SJacky Wang                   .onLineContaining("interface SelfComponent");
258*f585d8a3SJacky Wang             });
259*f585d8a3SJacky Wang   }
260*f585d8a3SJacky Wang 
261*f585d8a3SJacky Wang   @Test
genericInjectClassWithWildcardDependencies()262*f585d8a3SJacky Wang   public void genericInjectClassWithWildcardDependencies() {
263*f585d8a3SJacky Wang     Source component =
264*f585d8a3SJacky Wang         CompilerTests.javaSource(
265*f585d8a3SJacky Wang             "test.TestComponent",
266*f585d8a3SJacky Wang             "package test;",
267*f585d8a3SJacky Wang             "",
268*f585d8a3SJacky Wang             "import dagger.Component;",
269*f585d8a3SJacky Wang             "",
270*f585d8a3SJacky Wang             "@Component",
271*f585d8a3SJacky Wang             "interface TestComponent {",
272*f585d8a3SJacky Wang             "  Foo<? extends Number> foo();",
273*f585d8a3SJacky Wang             "}");
274*f585d8a3SJacky Wang     Source foo =
275*f585d8a3SJacky Wang         CompilerTests.javaSource(
276*f585d8a3SJacky Wang             "test.Foo",
277*f585d8a3SJacky Wang             "package test;",
278*f585d8a3SJacky Wang             "",
279*f585d8a3SJacky Wang             "import javax.inject.Inject;",
280*f585d8a3SJacky Wang             "",
281*f585d8a3SJacky Wang             "final class Foo<T> {",
282*f585d8a3SJacky Wang             "  @Inject Foo(T t) {}",
283*f585d8a3SJacky Wang             "}");
284*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, foo)
285*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
286*f585d8a3SJacky Wang         .compile(
287*f585d8a3SJacky Wang             subject -> {
288*f585d8a3SJacky Wang               subject.hasErrorCount(1);
289*f585d8a3SJacky Wang               subject.hasErrorContaining(
290*f585d8a3SJacky Wang                   "Foo<? extends Number> cannot be provided "
291*f585d8a3SJacky Wang                       + "without an @Provides-annotated method");
292*f585d8a3SJacky Wang             });
293*f585d8a3SJacky Wang   }
294*f585d8a3SJacky Wang 
longChainOfDependencies()295*f585d8a3SJacky Wang   @Test public void longChainOfDependencies() {
296*f585d8a3SJacky Wang     Source component =
297*f585d8a3SJacky Wang         CompilerTests.javaSource(
298*f585d8a3SJacky Wang             "test.TestClass",
299*f585d8a3SJacky Wang             "package test;",
300*f585d8a3SJacky Wang             "",
301*f585d8a3SJacky Wang             "import dagger.Component;",
302*f585d8a3SJacky Wang             "import dagger.Lazy;",
303*f585d8a3SJacky Wang             "import dagger.Module;",
304*f585d8a3SJacky Wang             "import dagger.Provides;",
305*f585d8a3SJacky Wang             "import javax.inject.Inject;",
306*f585d8a3SJacky Wang             "import javax.inject.Named;",
307*f585d8a3SJacky Wang             "import javax.inject.Provider;",
308*f585d8a3SJacky Wang             "",
309*f585d8a3SJacky Wang             "final class TestClass {",
310*f585d8a3SJacky Wang             "  interface A {}",
311*f585d8a3SJacky Wang             "",
312*f585d8a3SJacky Wang             "  static class B {",
313*f585d8a3SJacky Wang             "    @Inject B(A a) {}",
314*f585d8a3SJacky Wang             "  }",
315*f585d8a3SJacky Wang             "",
316*f585d8a3SJacky Wang             "  static class C {",
317*f585d8a3SJacky Wang             "    @Inject B b;",
318*f585d8a3SJacky Wang             "    @Inject C(X x) {}",
319*f585d8a3SJacky Wang             "  }",
320*f585d8a3SJacky Wang             "",
321*f585d8a3SJacky Wang             "  interface D { }",
322*f585d8a3SJacky Wang             "",
323*f585d8a3SJacky Wang             "  static class DImpl implements D {",
324*f585d8a3SJacky Wang             "    @Inject DImpl(C c, B b) {}",
325*f585d8a3SJacky Wang             "  }",
326*f585d8a3SJacky Wang             "",
327*f585d8a3SJacky Wang             "  static class X {",
328*f585d8a3SJacky Wang             "    @Inject X() {}",
329*f585d8a3SJacky Wang             "  }",
330*f585d8a3SJacky Wang             "",
331*f585d8a3SJacky Wang             "  @Module",
332*f585d8a3SJacky Wang             "  static class DModule {",
333*f585d8a3SJacky Wang             "    @Provides @Named(\"slim shady\") D d(X x1, DImpl impl, X x2) { return impl; }",
334*f585d8a3SJacky Wang             "  }",
335*f585d8a3SJacky Wang             "",
336*f585d8a3SJacky Wang             "  @Component(modules = { DModule.class })",
337*f585d8a3SJacky Wang             "  interface AComponent {",
338*f585d8a3SJacky Wang             "    @Named(\"slim shady\") D getFoo();",
339*f585d8a3SJacky Wang             "    C injectC(C c);",
340*f585d8a3SJacky Wang             "    Provider<C> cProvider();",
341*f585d8a3SJacky Wang             "    Lazy<C> lazyC();",
342*f585d8a3SJacky Wang             "    Provider<Lazy<C>> lazyCProvider();",
343*f585d8a3SJacky Wang             "  }",
344*f585d8a3SJacky Wang             "}");
345*f585d8a3SJacky Wang 
346*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
347*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
348*f585d8a3SJacky Wang         .compile(
349*f585d8a3SJacky Wang             subject -> {
350*f585d8a3SJacky Wang               subject.hasErrorCount(1);
351*f585d8a3SJacky Wang               subject.hasErrorContaining(
352*f585d8a3SJacky Wang                   String.join(
353*f585d8a3SJacky Wang                       "\n",
354*f585d8a3SJacky Wang                       "TestClass.A cannot be provided without an @Provides-annotated method.",
355*f585d8a3SJacky Wang                       "",
356*f585d8a3SJacky Wang                       "    TestClass.A is injected at",
357*f585d8a3SJacky Wang                       "        [TestClass.AComponent] TestClass.B(a)",
358*f585d8a3SJacky Wang                       "    TestClass.B is injected at",
359*f585d8a3SJacky Wang                       "        [TestClass.AComponent] TestClass.C.b",
360*f585d8a3SJacky Wang                       "    TestClass.C is injected at",
361*f585d8a3SJacky Wang                       "        [TestClass.AComponent] TestClass.AComponent.injectC(TestClass.C)",
362*f585d8a3SJacky Wang                       "The following other entry points also depend on it:",
363*f585d8a3SJacky Wang                       "    TestClass.AComponent.getFoo()",
364*f585d8a3SJacky Wang                       "    TestClass.AComponent.cProvider()",
365*f585d8a3SJacky Wang                       "    TestClass.AComponent.lazyC()",
366*f585d8a3SJacky Wang                       "    TestClass.AComponent.lazyCProvider()"))
367*f585d8a3SJacky Wang                   .onSource(component)
368*f585d8a3SJacky Wang                   .onLineContaining("interface AComponent");
369*f585d8a3SJacky Wang             });
370*f585d8a3SJacky Wang   }
371*f585d8a3SJacky Wang 
372*f585d8a3SJacky Wang   @Test
bindsMethodAppearsInTrace()373*f585d8a3SJacky Wang   public void bindsMethodAppearsInTrace() {
374*f585d8a3SJacky Wang     Source component =
375*f585d8a3SJacky Wang         CompilerTests.javaSource(
376*f585d8a3SJacky Wang             "TestComponent",
377*f585d8a3SJacky Wang             "import dagger.Component;",
378*f585d8a3SJacky Wang             "",
379*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
380*f585d8a3SJacky Wang             "interface TestComponent {",
381*f585d8a3SJacky Wang             "  TestInterface testInterface();",
382*f585d8a3SJacky Wang             "}");
383*f585d8a3SJacky Wang     Source interfaceFile =
384*f585d8a3SJacky Wang         CompilerTests.javaSource("TestInterface", "interface TestInterface {}");
385*f585d8a3SJacky Wang     Source implementationFile =
386*f585d8a3SJacky Wang         CompilerTests.javaSource(
387*f585d8a3SJacky Wang             "TestImplementation",
388*f585d8a3SJacky Wang             "import javax.inject.Inject;",
389*f585d8a3SJacky Wang             "",
390*f585d8a3SJacky Wang             "final class TestImplementation implements TestInterface {",
391*f585d8a3SJacky Wang             "  @Inject TestImplementation(String missingBinding) {}",
392*f585d8a3SJacky Wang             "}");
393*f585d8a3SJacky Wang     Source module =
394*f585d8a3SJacky Wang         CompilerTests.javaSource(
395*f585d8a3SJacky Wang             "TestModule",
396*f585d8a3SJacky Wang             "import dagger.Binds;",
397*f585d8a3SJacky Wang             "import dagger.Module;",
398*f585d8a3SJacky Wang             "",
399*f585d8a3SJacky Wang             "@Module",
400*f585d8a3SJacky Wang             "interface TestModule {",
401*f585d8a3SJacky Wang             "  @Binds abstract TestInterface bindTestInterface(TestImplementation implementation);",
402*f585d8a3SJacky Wang             "}");
403*f585d8a3SJacky Wang 
404*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, module, interfaceFile, implementationFile)
405*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
406*f585d8a3SJacky Wang         .compile(
407*f585d8a3SJacky Wang             subject -> {
408*f585d8a3SJacky Wang               subject.hasErrorCount(1);
409*f585d8a3SJacky Wang               subject.hasErrorContaining(
410*f585d8a3SJacky Wang                   String.join(
411*f585d8a3SJacky Wang                       "\n",
412*f585d8a3SJacky Wang                       "String cannot be provided without an @Inject constructor or an "
413*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
414*f585d8a3SJacky Wang                       "",
415*f585d8a3SJacky Wang                       "    String is injected at",
416*f585d8a3SJacky Wang                       "        [TestComponent] TestImplementation(missingBinding)",
417*f585d8a3SJacky Wang                       "    TestImplementation is injected at",
418*f585d8a3SJacky Wang                       "        [TestComponent] TestModule.bindTestInterface(implementation)",
419*f585d8a3SJacky Wang                       "    TestInterface is requested at",
420*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.testInterface()"))
421*f585d8a3SJacky Wang                   .onSource(component)
422*f585d8a3SJacky Wang                   .onLineContaining("interface TestComponent");
423*f585d8a3SJacky Wang             });
424*f585d8a3SJacky Wang   }
425*f585d8a3SJacky Wang 
resolvedParametersInDependencyTrace()426*f585d8a3SJacky Wang   @Test public void resolvedParametersInDependencyTrace() {
427*f585d8a3SJacky Wang     Source generic =
428*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Generic",
429*f585d8a3SJacky Wang         "package test;",
430*f585d8a3SJacky Wang         "",
431*f585d8a3SJacky Wang         "import javax.inject.Inject;",
432*f585d8a3SJacky Wang         "import javax.inject.Provider;",
433*f585d8a3SJacky Wang         "",
434*f585d8a3SJacky Wang         "final class Generic<T> {",
435*f585d8a3SJacky Wang         "  @Inject Generic(T t) {}",
436*f585d8a3SJacky Wang         "}");
437*f585d8a3SJacky Wang     Source testClass =
438*f585d8a3SJacky Wang         CompilerTests.javaSource("test.TestClass",
439*f585d8a3SJacky Wang         "package test;",
440*f585d8a3SJacky Wang         "",
441*f585d8a3SJacky Wang         "import javax.inject.Inject;",
442*f585d8a3SJacky Wang         "import java.util.List;",
443*f585d8a3SJacky Wang         "",
444*f585d8a3SJacky Wang         "final class TestClass {",
445*f585d8a3SJacky Wang         "  @Inject TestClass(List list) {}",
446*f585d8a3SJacky Wang         "}");
447*f585d8a3SJacky Wang     Source usesTest =
448*f585d8a3SJacky Wang         CompilerTests.javaSource("test.UsesTest",
449*f585d8a3SJacky Wang         "package test;",
450*f585d8a3SJacky Wang         "",
451*f585d8a3SJacky Wang         "import javax.inject.Inject;",
452*f585d8a3SJacky Wang         "",
453*f585d8a3SJacky Wang         "final class UsesTest {",
454*f585d8a3SJacky Wang         "  @Inject UsesTest(Generic<TestClass> genericTestClass) {}",
455*f585d8a3SJacky Wang         "}");
456*f585d8a3SJacky Wang     Source component =
457*f585d8a3SJacky Wang         CompilerTests.javaSource("test.TestComponent",
458*f585d8a3SJacky Wang         "package test;",
459*f585d8a3SJacky Wang         "",
460*f585d8a3SJacky Wang         "import dagger.Component;",
461*f585d8a3SJacky Wang         "",
462*f585d8a3SJacky Wang         "@Component",
463*f585d8a3SJacky Wang         "interface TestComponent {",
464*f585d8a3SJacky Wang         "  UsesTest usesTest();",
465*f585d8a3SJacky Wang         "}");
466*f585d8a3SJacky Wang 
467*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(generic, testClass, usesTest, component)
468*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
469*f585d8a3SJacky Wang         .compile(
470*f585d8a3SJacky Wang             subject -> {
471*f585d8a3SJacky Wang               subject.hasErrorCount(1);
472*f585d8a3SJacky Wang               subject.hasErrorContaining(
473*f585d8a3SJacky Wang                   String.join(
474*f585d8a3SJacky Wang                       "\n",
475*f585d8a3SJacky Wang                       "List cannot be provided without an @Provides-annotated method.",
476*f585d8a3SJacky Wang                       "",
477*f585d8a3SJacky Wang                       "    List is injected at",
478*f585d8a3SJacky Wang                       "        [TestComponent] TestClass(list)",
479*f585d8a3SJacky Wang                       "    TestClass is injected at",
480*f585d8a3SJacky Wang                       "        [TestComponent] Generic(t)",
481*f585d8a3SJacky Wang                       "    Generic<TestClass> is injected at",
482*f585d8a3SJacky Wang                       "        [TestComponent] UsesTest(genericTestClass)",
483*f585d8a3SJacky Wang                       "    UsesTest is requested at",
484*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.usesTest()"));
485*f585d8a3SJacky Wang             });
486*f585d8a3SJacky Wang   }
487*f585d8a3SJacky Wang 
resolvedVariablesInDependencyTrace()488*f585d8a3SJacky Wang   @Test public void resolvedVariablesInDependencyTrace() {
489*f585d8a3SJacky Wang     Source generic =
490*f585d8a3SJacky Wang         CompilerTests.javaSource(
491*f585d8a3SJacky Wang             "test.Generic",
492*f585d8a3SJacky Wang             "package test;",
493*f585d8a3SJacky Wang             "",
494*f585d8a3SJacky Wang             "import javax.inject.Inject;",
495*f585d8a3SJacky Wang             "import javax.inject.Provider;",
496*f585d8a3SJacky Wang             "",
497*f585d8a3SJacky Wang             "final class Generic<T> {",
498*f585d8a3SJacky Wang             "  @Inject T t;",
499*f585d8a3SJacky Wang             "  @Inject Generic() {}",
500*f585d8a3SJacky Wang             "}");
501*f585d8a3SJacky Wang     Source testClass =
502*f585d8a3SJacky Wang         CompilerTests.javaSource(
503*f585d8a3SJacky Wang             "test.TestClass",
504*f585d8a3SJacky Wang             "package test;",
505*f585d8a3SJacky Wang             "",
506*f585d8a3SJacky Wang             "import javax.inject.Inject;",
507*f585d8a3SJacky Wang             "import java.util.List;",
508*f585d8a3SJacky Wang             "",
509*f585d8a3SJacky Wang             "final class TestClass {",
510*f585d8a3SJacky Wang             "  @Inject TestClass(List list) {}",
511*f585d8a3SJacky Wang             "}");
512*f585d8a3SJacky Wang     Source usesTest =
513*f585d8a3SJacky Wang         CompilerTests.javaSource(
514*f585d8a3SJacky Wang             "test.UsesTest",
515*f585d8a3SJacky Wang             "package test;",
516*f585d8a3SJacky Wang             "",
517*f585d8a3SJacky Wang             "import javax.inject.Inject;",
518*f585d8a3SJacky Wang             "",
519*f585d8a3SJacky Wang             "final class UsesTest {",
520*f585d8a3SJacky Wang             "  @Inject UsesTest(Generic<TestClass> genericTestClass) {}",
521*f585d8a3SJacky Wang             "}");
522*f585d8a3SJacky Wang     Source component =
523*f585d8a3SJacky Wang         CompilerTests.javaSource(
524*f585d8a3SJacky Wang             "test.TestComponent",
525*f585d8a3SJacky Wang             "package test;",
526*f585d8a3SJacky Wang             "",
527*f585d8a3SJacky Wang             "import dagger.Component;",
528*f585d8a3SJacky Wang             "",
529*f585d8a3SJacky Wang             "@Component",
530*f585d8a3SJacky Wang             "interface TestComponent {",
531*f585d8a3SJacky Wang             "  UsesTest usesTest();",
532*f585d8a3SJacky Wang             "}");
533*f585d8a3SJacky Wang 
534*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(generic, testClass, usesTest, component)
535*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
536*f585d8a3SJacky Wang         .compile(
537*f585d8a3SJacky Wang             subject -> {
538*f585d8a3SJacky Wang               subject.hasErrorCount(1);
539*f585d8a3SJacky Wang               subject.hasErrorContaining(
540*f585d8a3SJacky Wang                   String.join(
541*f585d8a3SJacky Wang                       "\n",
542*f585d8a3SJacky Wang                       "List cannot be provided without an @Provides-annotated method.",
543*f585d8a3SJacky Wang                       "",
544*f585d8a3SJacky Wang                       "    List is injected at",
545*f585d8a3SJacky Wang                       "        [TestComponent] TestClass(list)",
546*f585d8a3SJacky Wang                       "    TestClass is injected at",
547*f585d8a3SJacky Wang                       "        [TestComponent] Generic.t",
548*f585d8a3SJacky Wang                       "    Generic<TestClass> is injected at",
549*f585d8a3SJacky Wang                       "        [TestComponent] UsesTest(genericTestClass)",
550*f585d8a3SJacky Wang                       "    UsesTest is requested at",
551*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.usesTest()"));
552*f585d8a3SJacky Wang             });
553*f585d8a3SJacky Wang   }
554*f585d8a3SJacky Wang 
555*f585d8a3SJacky Wang   @Test
bindingUsedOnlyInSubcomponentDependsOnBindingOnlyInSubcomponent()556*f585d8a3SJacky Wang   public void bindingUsedOnlyInSubcomponentDependsOnBindingOnlyInSubcomponent() {
557*f585d8a3SJacky Wang     Source parent =
558*f585d8a3SJacky Wang         CompilerTests.javaSource(
559*f585d8a3SJacky Wang             "Parent",
560*f585d8a3SJacky Wang             "import dagger.Component;",
561*f585d8a3SJacky Wang             "",
562*f585d8a3SJacky Wang             "@Component(modules = ParentModule.class)",
563*f585d8a3SJacky Wang             "interface Parent {",
564*f585d8a3SJacky Wang             "  Child child();",
565*f585d8a3SJacky Wang             "}");
566*f585d8a3SJacky Wang     Source parentModule =
567*f585d8a3SJacky Wang         CompilerTests.javaSource(
568*f585d8a3SJacky Wang             "ParentModule",
569*f585d8a3SJacky Wang             "import dagger.Module;",
570*f585d8a3SJacky Wang             "import dagger.Provides;",
571*f585d8a3SJacky Wang             "",
572*f585d8a3SJacky Wang             "@Module",
573*f585d8a3SJacky Wang             "class ParentModule {",
574*f585d8a3SJacky Wang             "  @Provides static Object needsString(String string) {",
575*f585d8a3SJacky Wang             "    return \"needs string: \" + string;",
576*f585d8a3SJacky Wang             "  }",
577*f585d8a3SJacky Wang             "}");
578*f585d8a3SJacky Wang     Source child =
579*f585d8a3SJacky Wang         CompilerTests.javaSource(
580*f585d8a3SJacky Wang             "Child",
581*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
582*f585d8a3SJacky Wang             "",
583*f585d8a3SJacky Wang             "@Subcomponent(modules = ChildModule.class)",
584*f585d8a3SJacky Wang             "interface Child {",
585*f585d8a3SJacky Wang             "  String string();",
586*f585d8a3SJacky Wang             "  Object needsString();",
587*f585d8a3SJacky Wang             "}");
588*f585d8a3SJacky Wang     Source childModule =
589*f585d8a3SJacky Wang         CompilerTests.javaSource(
590*f585d8a3SJacky Wang             "ChildModule",
591*f585d8a3SJacky Wang             "import dagger.Module;",
592*f585d8a3SJacky Wang             "import dagger.Provides;",
593*f585d8a3SJacky Wang             "",
594*f585d8a3SJacky Wang             "@Module",
595*f585d8a3SJacky Wang             "class ChildModule {",
596*f585d8a3SJacky Wang             "  @Provides static String string() {",
597*f585d8a3SJacky Wang             "    return \"child string\";",
598*f585d8a3SJacky Wang             "  }",
599*f585d8a3SJacky Wang             "}");
600*f585d8a3SJacky Wang 
601*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(parent, parentModule, child, childModule)
602*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
603*f585d8a3SJacky Wang         .compile(
604*f585d8a3SJacky Wang             subject -> {
605*f585d8a3SJacky Wang               subject.hasErrorCount(1);
606*f585d8a3SJacky Wang               subject.hasErrorContaining("String cannot be provided");
607*f585d8a3SJacky Wang               subject.hasErrorContaining("[Child] Child.needsString()")
608*f585d8a3SJacky Wang                   .onSource(parent)
609*f585d8a3SJacky Wang                   .onLineContaining("interface Parent");
610*f585d8a3SJacky Wang             });
611*f585d8a3SJacky Wang   }
612*f585d8a3SJacky Wang 
613*f585d8a3SJacky Wang   @Test
multibindingContributionBetweenAncestorComponentAndEntrypointComponent()614*f585d8a3SJacky Wang   public void multibindingContributionBetweenAncestorComponentAndEntrypointComponent() {
615*f585d8a3SJacky Wang     Source parent =
616*f585d8a3SJacky Wang         CompilerTests.javaSource(
617*f585d8a3SJacky Wang             "Parent",
618*f585d8a3SJacky Wang             "import dagger.Component;",
619*f585d8a3SJacky Wang             "",
620*f585d8a3SJacky Wang             "@Component(modules = ParentModule.class)",
621*f585d8a3SJacky Wang             "interface Parent {",
622*f585d8a3SJacky Wang             "  Child child();",
623*f585d8a3SJacky Wang             "}");
624*f585d8a3SJacky Wang     Source child =
625*f585d8a3SJacky Wang         CompilerTests.javaSource(
626*f585d8a3SJacky Wang             "Child",
627*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
628*f585d8a3SJacky Wang             "",
629*f585d8a3SJacky Wang             "@Subcomponent(modules = ChildModule.class)",
630*f585d8a3SJacky Wang             "interface Child {",
631*f585d8a3SJacky Wang             "  Grandchild grandchild();",
632*f585d8a3SJacky Wang             "}");
633*f585d8a3SJacky Wang     Source grandchild =
634*f585d8a3SJacky Wang         CompilerTests.javaSource(
635*f585d8a3SJacky Wang             "Grandchild",
636*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
637*f585d8a3SJacky Wang             "",
638*f585d8a3SJacky Wang             "@Subcomponent",
639*f585d8a3SJacky Wang             "interface Grandchild {",
640*f585d8a3SJacky Wang             "  Object object();",
641*f585d8a3SJacky Wang             "}");
642*f585d8a3SJacky Wang 
643*f585d8a3SJacky Wang     Source parentModule =
644*f585d8a3SJacky Wang         CompilerTests.javaSource(
645*f585d8a3SJacky Wang             "ParentModule",
646*f585d8a3SJacky Wang             "import dagger.Module;",
647*f585d8a3SJacky Wang             "import dagger.Provides;",
648*f585d8a3SJacky Wang             "import dagger.multibindings.IntoSet;",
649*f585d8a3SJacky Wang             "import java.util.Set;",
650*f585d8a3SJacky Wang             "",
651*f585d8a3SJacky Wang             "@Module",
652*f585d8a3SJacky Wang             "class ParentModule {",
653*f585d8a3SJacky Wang             "  @Provides static Object dependsOnSet(Set<String> strings) {",
654*f585d8a3SJacky Wang             "    return \"needs strings: \" + strings;",
655*f585d8a3SJacky Wang             "  }",
656*f585d8a3SJacky Wang             "",
657*f585d8a3SJacky Wang             "  @Provides @IntoSet static String contributesToSet() {",
658*f585d8a3SJacky Wang             "    return \"parent string\";",
659*f585d8a3SJacky Wang             "  }",
660*f585d8a3SJacky Wang             "",
661*f585d8a3SJacky Wang             "  @Provides int missingDependency(double dub) {",
662*f585d8a3SJacky Wang             "    return 4;",
663*f585d8a3SJacky Wang             "  }",
664*f585d8a3SJacky Wang             "}");
665*f585d8a3SJacky Wang     Source childModule =
666*f585d8a3SJacky Wang         CompilerTests.javaSource(
667*f585d8a3SJacky Wang             "ChildModule",
668*f585d8a3SJacky Wang             "import dagger.Module;",
669*f585d8a3SJacky Wang             "import dagger.Provides;",
670*f585d8a3SJacky Wang             "import dagger.multibindings.IntoSet;",
671*f585d8a3SJacky Wang             "",
672*f585d8a3SJacky Wang             "@Module",
673*f585d8a3SJacky Wang             "class ChildModule {",
674*f585d8a3SJacky Wang             "  @Provides @IntoSet static String contributesToSet(int i) {",
675*f585d8a3SJacky Wang             "    return \"\" + i;",
676*f585d8a3SJacky Wang             "  }",
677*f585d8a3SJacky Wang             "}");
678*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(parent, parentModule, child, childModule, grandchild)
679*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
680*f585d8a3SJacky Wang         .compile(
681*f585d8a3SJacky Wang             subject -> {
682*f585d8a3SJacky Wang               subject.hasErrorCount(1);
683*f585d8a3SJacky Wang               // TODO(b/243720787): Replace with CompilationResultSubject#hasErrorContainingMatch()
684*f585d8a3SJacky Wang               subject.hasErrorContaining(
685*f585d8a3SJacky Wang                   String.join(
686*f585d8a3SJacky Wang                       "\n",
687*f585d8a3SJacky Wang                       "Double cannot be provided without an @Inject constructor or an "
688*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
689*f585d8a3SJacky Wang                       "",
690*f585d8a3SJacky Wang                       "    Double is injected at",
691*f585d8a3SJacky Wang                       "        [Parent] ParentModule.missingDependency(dub)",
692*f585d8a3SJacky Wang                       "    Integer is injected at",
693*f585d8a3SJacky Wang                       "        [Child] ChildModule.contributesToSet(i)",
694*f585d8a3SJacky Wang                       "    Set<String> is injected at",
695*f585d8a3SJacky Wang                       "        [Child] ParentModule.dependsOnSet(strings)",
696*f585d8a3SJacky Wang                       "    Object is requested at",
697*f585d8a3SJacky Wang                       "        [Grandchild] Grandchild.object() [Parent → Child → Grandchild]"))
698*f585d8a3SJacky Wang                   .onSource(parent)
699*f585d8a3SJacky Wang                   .onLineContaining("interface Parent");
700*f585d8a3SJacky Wang             });
701*f585d8a3SJacky Wang   }
702*f585d8a3SJacky Wang 
703*f585d8a3SJacky Wang   @Test
manyDependencies()704*f585d8a3SJacky Wang   public void manyDependencies() {
705*f585d8a3SJacky Wang     Source component =
706*f585d8a3SJacky Wang         CompilerTests.javaSource(
707*f585d8a3SJacky Wang             "test.TestComponent",
708*f585d8a3SJacky Wang             "package test;",
709*f585d8a3SJacky Wang             "",
710*f585d8a3SJacky Wang             "import dagger.Component;",
711*f585d8a3SJacky Wang             "",
712*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
713*f585d8a3SJacky Wang             "interface TestComponent {",
714*f585d8a3SJacky Wang             "  Object object();",
715*f585d8a3SJacky Wang             "  String string();",
716*f585d8a3SJacky Wang             "}");
717*f585d8a3SJacky Wang     Source module =
718*f585d8a3SJacky Wang         CompilerTests.javaSource(
719*f585d8a3SJacky Wang             "test.TestModule",
720*f585d8a3SJacky Wang             "package test;",
721*f585d8a3SJacky Wang             "",
722*f585d8a3SJacky Wang             "import dagger.Binds;",
723*f585d8a3SJacky Wang             "import dagger.Module;",
724*f585d8a3SJacky Wang             "import dagger.Provides;",
725*f585d8a3SJacky Wang             "",
726*f585d8a3SJacky Wang             "@Module",
727*f585d8a3SJacky Wang             "abstract class TestModule {",
728*f585d8a3SJacky Wang             "  @Binds abstract Object object(NotBound notBound);",
729*f585d8a3SJacky Wang             "",
730*f585d8a3SJacky Wang             "  @Provides static String string(NotBound notBound, Object object) {",
731*f585d8a3SJacky Wang             "    return notBound.toString();",
732*f585d8a3SJacky Wang             "  }",
733*f585d8a3SJacky Wang             "}");
734*f585d8a3SJacky Wang     Source notBound =
735*f585d8a3SJacky Wang         CompilerTests.javaSource(
736*f585d8a3SJacky Wang             "test.NotBound", //
737*f585d8a3SJacky Wang             "package test;",
738*f585d8a3SJacky Wang             "",
739*f585d8a3SJacky Wang             "interface NotBound {}");
740*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, module, notBound)
741*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
742*f585d8a3SJacky Wang         .compile(
743*f585d8a3SJacky Wang             subject -> {
744*f585d8a3SJacky Wang               subject.hasErrorCount(1);
745*f585d8a3SJacky Wang               subject.hasErrorContaining(
746*f585d8a3SJacky Wang                   String.join(
747*f585d8a3SJacky Wang                       "\n",
748*f585d8a3SJacky Wang                       "NotBound cannot be provided without an @Provides-annotated method.",
749*f585d8a3SJacky Wang                       "",
750*f585d8a3SJacky Wang                       "    NotBound is injected at",
751*f585d8a3SJacky Wang                       "        [TestComponent] TestModule.object(notBound)",
752*f585d8a3SJacky Wang                       "    Object is requested at",
753*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.object()",
754*f585d8a3SJacky Wang                       "It is also requested at:",
755*f585d8a3SJacky Wang                       "    TestModule.string(notBound, …)",
756*f585d8a3SJacky Wang                       "The following other entry points also depend on it:",
757*f585d8a3SJacky Wang                       "    TestComponent.string()"))
758*f585d8a3SJacky Wang                   .onSource(component)
759*f585d8a3SJacky Wang                   .onLineContaining("interface TestComponent");
760*f585d8a3SJacky Wang             });
761*f585d8a3SJacky Wang   }
762*f585d8a3SJacky Wang 
763*f585d8a3SJacky Wang   @Test
tooManyRequests()764*f585d8a3SJacky Wang   public void tooManyRequests() {
765*f585d8a3SJacky Wang     Source foo =
766*f585d8a3SJacky Wang         CompilerTests.javaSource(
767*f585d8a3SJacky Wang             "test.Foo",
768*f585d8a3SJacky Wang             "package test;",
769*f585d8a3SJacky Wang             "",
770*f585d8a3SJacky Wang             "import javax.inject.Inject;",
771*f585d8a3SJacky Wang             "",
772*f585d8a3SJacky Wang             "final class Foo {",
773*f585d8a3SJacky Wang             "  @Inject Foo(",
774*f585d8a3SJacky Wang             "      String one,",
775*f585d8a3SJacky Wang             "      String two,",
776*f585d8a3SJacky Wang             "      String three,",
777*f585d8a3SJacky Wang             "      String four,",
778*f585d8a3SJacky Wang             "      String five,",
779*f585d8a3SJacky Wang             "      String six,",
780*f585d8a3SJacky Wang             "      String seven,",
781*f585d8a3SJacky Wang             "      String eight,",
782*f585d8a3SJacky Wang             "      String nine,",
783*f585d8a3SJacky Wang             "      String ten,",
784*f585d8a3SJacky Wang             "      String eleven,",
785*f585d8a3SJacky Wang             "      String twelve,",
786*f585d8a3SJacky Wang             "      String thirteen) {",
787*f585d8a3SJacky Wang             "  }",
788*f585d8a3SJacky Wang             "}");
789*f585d8a3SJacky Wang     Source component =
790*f585d8a3SJacky Wang         CompilerTests.javaSource(
791*f585d8a3SJacky Wang             "test.TestComponent",
792*f585d8a3SJacky Wang             "package test;",
793*f585d8a3SJacky Wang             "",
794*f585d8a3SJacky Wang             "import dagger.Component;",
795*f585d8a3SJacky Wang             "",
796*f585d8a3SJacky Wang             "@Component",
797*f585d8a3SJacky Wang             "interface TestComponent {",
798*f585d8a3SJacky Wang             "  String string();",
799*f585d8a3SJacky Wang             "  Foo foo();",
800*f585d8a3SJacky Wang             "}");
801*f585d8a3SJacky Wang 
802*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(foo, component)
803*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
804*f585d8a3SJacky Wang         .compile(
805*f585d8a3SJacky Wang             subject -> {
806*f585d8a3SJacky Wang               subject.hasErrorCount(1);
807*f585d8a3SJacky Wang               subject.hasErrorContaining(
808*f585d8a3SJacky Wang                   String.join(
809*f585d8a3SJacky Wang                       "\n",
810*f585d8a3SJacky Wang                       "String cannot be provided without an @Inject constructor or an "
811*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
812*f585d8a3SJacky Wang                       "",
813*f585d8a3SJacky Wang                       "    String is requested at",
814*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.string()",
815*f585d8a3SJacky Wang                       "It is also requested at:",
816*f585d8a3SJacky Wang                       "    Foo(one, …)",
817*f585d8a3SJacky Wang                       "    Foo(…, two, …)",
818*f585d8a3SJacky Wang                       "    Foo(…, three, …)",
819*f585d8a3SJacky Wang                       "    Foo(…, four, …)",
820*f585d8a3SJacky Wang                       "    Foo(…, five, …)",
821*f585d8a3SJacky Wang                       "    Foo(…, six, …)",
822*f585d8a3SJacky Wang                       "    Foo(…, seven, …)",
823*f585d8a3SJacky Wang                       "    Foo(…, eight, …)",
824*f585d8a3SJacky Wang                       "    Foo(…, nine, …)",
825*f585d8a3SJacky Wang                       "    Foo(…, ten, …)",
826*f585d8a3SJacky Wang                       "    and 3 others",
827*f585d8a3SJacky Wang                       "The following other entry points also depend on it:",
828*f585d8a3SJacky Wang                       "    TestComponent.foo()"))
829*f585d8a3SJacky Wang                   .onSource(component)
830*f585d8a3SJacky Wang                   .onLineContaining("interface TestComponent");
831*f585d8a3SJacky Wang             });
832*f585d8a3SJacky Wang   }
833*f585d8a3SJacky Wang 
834*f585d8a3SJacky Wang   @Test
tooManyEntryPoints()835*f585d8a3SJacky Wang   public void tooManyEntryPoints() {
836*f585d8a3SJacky Wang     Source component =
837*f585d8a3SJacky Wang         CompilerTests.javaSource(
838*f585d8a3SJacky Wang             "test.TestComponent",
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 TestComponent {",
845*f585d8a3SJacky Wang             "  String string1();",
846*f585d8a3SJacky Wang             "  String string2();",
847*f585d8a3SJacky Wang             "  String string3();",
848*f585d8a3SJacky Wang             "  String string4();",
849*f585d8a3SJacky Wang             "  String string5();",
850*f585d8a3SJacky Wang             "  String string6();",
851*f585d8a3SJacky Wang             "  String string7();",
852*f585d8a3SJacky Wang             "  String string8();",
853*f585d8a3SJacky Wang             "  String string9();",
854*f585d8a3SJacky Wang             "  String string10();",
855*f585d8a3SJacky Wang             "  String string11();",
856*f585d8a3SJacky Wang             "  String string12();",
857*f585d8a3SJacky Wang             "}");
858*f585d8a3SJacky Wang 
859*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component)
860*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
861*f585d8a3SJacky Wang         .compile(
862*f585d8a3SJacky Wang             subject -> {
863*f585d8a3SJacky Wang               subject.hasErrorCount(1);
864*f585d8a3SJacky Wang               subject.hasErrorContaining(
865*f585d8a3SJacky Wang                   String.join(
866*f585d8a3SJacky Wang                       "\n",
867*f585d8a3SJacky Wang                       "String cannot be provided without an @Inject constructor or an "
868*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
869*f585d8a3SJacky Wang                       "",
870*f585d8a3SJacky Wang                       "    String is requested at",
871*f585d8a3SJacky Wang                       "        [TestComponent] TestComponent.string1()",
872*f585d8a3SJacky Wang                       "The following other entry points also depend on it:",
873*f585d8a3SJacky Wang                       "    TestComponent.string2()",
874*f585d8a3SJacky Wang                       "    TestComponent.string3()",
875*f585d8a3SJacky Wang                       "    TestComponent.string4()",
876*f585d8a3SJacky Wang                       "    TestComponent.string5()",
877*f585d8a3SJacky Wang                       "    TestComponent.string6()",
878*f585d8a3SJacky Wang                       "    TestComponent.string7()",
879*f585d8a3SJacky Wang                       "    TestComponent.string8()",
880*f585d8a3SJacky Wang                       "    TestComponent.string9()",
881*f585d8a3SJacky Wang                       "    TestComponent.string10()",
882*f585d8a3SJacky Wang                       "    TestComponent.string11()",
883*f585d8a3SJacky Wang                       "    and 1 other"))
884*f585d8a3SJacky Wang                   .onSource(component)
885*f585d8a3SJacky Wang                   .onLineContaining("interface TestComponent");
886*f585d8a3SJacky Wang             });
887*f585d8a3SJacky Wang   }
888*f585d8a3SJacky Wang 
889*f585d8a3SJacky Wang   @Test
missingBindingInAllComponentsAndEntryPoints()890*f585d8a3SJacky Wang   public void missingBindingInAllComponentsAndEntryPoints() {
891*f585d8a3SJacky Wang     Source parent =
892*f585d8a3SJacky Wang         CompilerTests.javaSource(
893*f585d8a3SJacky Wang             "Parent",
894*f585d8a3SJacky Wang             "import dagger.Component;",
895*f585d8a3SJacky Wang             "",
896*f585d8a3SJacky Wang             "@Component",
897*f585d8a3SJacky Wang             "interface Parent {",
898*f585d8a3SJacky Wang             "  Foo foo();",
899*f585d8a3SJacky Wang             "  Bar bar();",
900*f585d8a3SJacky Wang             "  Child child();",
901*f585d8a3SJacky Wang             "}");
902*f585d8a3SJacky Wang     Source child =
903*f585d8a3SJacky Wang         CompilerTests.javaSource(
904*f585d8a3SJacky Wang             "Child",
905*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
906*f585d8a3SJacky Wang             "",
907*f585d8a3SJacky Wang             "@Subcomponent",
908*f585d8a3SJacky Wang             "interface Child {",
909*f585d8a3SJacky Wang             "  Foo foo();",
910*f585d8a3SJacky Wang             "  Baz baz();",
911*f585d8a3SJacky Wang             "}");
912*f585d8a3SJacky Wang     Source foo =
913*f585d8a3SJacky Wang         CompilerTests.javaSource(
914*f585d8a3SJacky Wang             "Foo",
915*f585d8a3SJacky Wang             "import javax.inject.Inject;",
916*f585d8a3SJacky Wang             "",
917*f585d8a3SJacky Wang             "class Foo {",
918*f585d8a3SJacky Wang             "  @Inject Foo(Bar bar) {}",
919*f585d8a3SJacky Wang             "}");
920*f585d8a3SJacky Wang     Source bar =
921*f585d8a3SJacky Wang         CompilerTests.javaSource(
922*f585d8a3SJacky Wang             "Bar",
923*f585d8a3SJacky Wang             "import javax.inject.Inject;",
924*f585d8a3SJacky Wang             "",
925*f585d8a3SJacky Wang             "class Bar {",
926*f585d8a3SJacky Wang             "  @Inject Bar(Baz baz) {}",
927*f585d8a3SJacky Wang             "}");
928*f585d8a3SJacky Wang     Source baz =
929*f585d8a3SJacky Wang         CompilerTests.javaSource("Baz", "class Baz {}");
930*f585d8a3SJacky Wang 
931*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(parent, child, foo, bar, baz)
932*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
933*f585d8a3SJacky Wang         .compile(
934*f585d8a3SJacky Wang             subject -> {
935*f585d8a3SJacky Wang               subject.hasErrorCount(1);
936*f585d8a3SJacky Wang               subject.hasErrorContaining(
937*f585d8a3SJacky Wang                   String.join(
938*f585d8a3SJacky Wang                       "\n",
939*f585d8a3SJacky Wang                       "Baz cannot be provided without an @Inject constructor or an "
940*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
941*f585d8a3SJacky Wang                       "",
942*f585d8a3SJacky Wang                       "    Baz is injected at",
943*f585d8a3SJacky Wang                       "        [Parent] Bar(baz)",
944*f585d8a3SJacky Wang                       "    Bar is requested at",
945*f585d8a3SJacky Wang                       "        [Parent] Parent.bar()",
946*f585d8a3SJacky Wang                       "The following other entry points also depend on it:",
947*f585d8a3SJacky Wang                       "    Parent.foo()",
948*f585d8a3SJacky Wang                       "    Child.foo() [Parent → Child]",
949*f585d8a3SJacky Wang                       "    Child.baz() [Parent → Child]"))
950*f585d8a3SJacky Wang                   .onSource(parent)
951*f585d8a3SJacky Wang                   .onLineContaining("interface Parent");
952*f585d8a3SJacky Wang             });
953*f585d8a3SJacky Wang   }
954*f585d8a3SJacky Wang 
955*f585d8a3SJacky Wang   // Regression test for b/147423208 where if the same subcomponent was used
956*f585d8a3SJacky Wang   // in two different parts of the hierarchy and only one side had a missing binding
957*f585d8a3SJacky Wang   // incorrect caching during binding graph conversion might cause validation to pass
958*f585d8a3SJacky Wang   // incorrectly.
959*f585d8a3SJacky Wang   @Test
sameSubcomponentUsedInDifferentHierarchies()960*f585d8a3SJacky Wang   public void sameSubcomponentUsedInDifferentHierarchies() {
961*f585d8a3SJacky Wang     Source parent =
962*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Parent",
963*f585d8a3SJacky Wang         "package test;",
964*f585d8a3SJacky Wang         "",
965*f585d8a3SJacky Wang         "import dagger.Component;",
966*f585d8a3SJacky Wang         "",
967*f585d8a3SJacky Wang         "@Component",
968*f585d8a3SJacky Wang         "interface Parent {",
969*f585d8a3SJacky Wang         "  Child1 getChild1();",
970*f585d8a3SJacky Wang         "  Child2 getChild2();",
971*f585d8a3SJacky Wang         "}");
972*f585d8a3SJacky Wang     Source child1 =
973*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Child1",
974*f585d8a3SJacky Wang         "package test;",
975*f585d8a3SJacky Wang         "",
976*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
977*f585d8a3SJacky Wang         "",
978*f585d8a3SJacky Wang         "@Subcomponent(modules = LongModule.class)",
979*f585d8a3SJacky Wang         "interface Child1 {",
980*f585d8a3SJacky Wang         "  RepeatedSub getSub();",
981*f585d8a3SJacky Wang         "}");
982*f585d8a3SJacky Wang     Source child2 =
983*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Child2",
984*f585d8a3SJacky Wang         "package test;",
985*f585d8a3SJacky Wang         "",
986*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
987*f585d8a3SJacky Wang         "",
988*f585d8a3SJacky Wang         "@Subcomponent",
989*f585d8a3SJacky Wang         "interface Child2 {",
990*f585d8a3SJacky Wang         "  RepeatedSub getSub();",
991*f585d8a3SJacky Wang         "}");
992*f585d8a3SJacky Wang     Source repeatedSub =
993*f585d8a3SJacky Wang         CompilerTests.javaSource("test.RepeatedSub",
994*f585d8a3SJacky Wang         "package test;",
995*f585d8a3SJacky Wang         "",
996*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
997*f585d8a3SJacky Wang         "",
998*f585d8a3SJacky Wang         "@Subcomponent",
999*f585d8a3SJacky Wang         "interface RepeatedSub {",
1000*f585d8a3SJacky Wang         "  Foo getFoo();",
1001*f585d8a3SJacky Wang         "}");
1002*f585d8a3SJacky Wang     Source injectable =
1003*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Foo",
1004*f585d8a3SJacky Wang         "package test;",
1005*f585d8a3SJacky Wang         "",
1006*f585d8a3SJacky Wang         "import javax.inject.Inject;",
1007*f585d8a3SJacky Wang         "",
1008*f585d8a3SJacky Wang         "class Foo {",
1009*f585d8a3SJacky Wang         "  @Inject Foo(Long value) {}",
1010*f585d8a3SJacky Wang         "}");
1011*f585d8a3SJacky Wang     Source module =
1012*f585d8a3SJacky Wang         CompilerTests.javaSource("test.LongModule",
1013*f585d8a3SJacky Wang         "package test;",
1014*f585d8a3SJacky Wang         "",
1015*f585d8a3SJacky Wang         "import dagger.Module;",
1016*f585d8a3SJacky Wang         "import dagger.Provides;",
1017*f585d8a3SJacky Wang         "",
1018*f585d8a3SJacky Wang         "@Module",
1019*f585d8a3SJacky Wang         "interface LongModule {",
1020*f585d8a3SJacky Wang         "  @Provides static Long provideLong() {",
1021*f585d8a3SJacky Wang         "    return 0L;",
1022*f585d8a3SJacky Wang         "  }",
1023*f585d8a3SJacky Wang         "}");
1024*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(parent, child1, child2, repeatedSub, injectable, module)
1025*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1026*f585d8a3SJacky Wang         .compile(
1027*f585d8a3SJacky Wang             subject -> {
1028*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1029*f585d8a3SJacky Wang               subject.hasErrorContaining("Long cannot be provided without an @Inject constructor")
1030*f585d8a3SJacky Wang                   .onSource(parent)
1031*f585d8a3SJacky Wang                   .onLineContaining("interface Parent");
1032*f585d8a3SJacky Wang             });
1033*f585d8a3SJacky Wang   }
1034*f585d8a3SJacky Wang 
1035*f585d8a3SJacky Wang   @Test
requestUnusedBindingInDifferentComponent()1036*f585d8a3SJacky Wang   public void requestUnusedBindingInDifferentComponent() {
1037*f585d8a3SJacky Wang     Source parent =
1038*f585d8a3SJacky Wang         CompilerTests.javaSource(
1039*f585d8a3SJacky Wang             "test.Parent",
1040*f585d8a3SJacky Wang             "package test;",
1041*f585d8a3SJacky Wang             "",
1042*f585d8a3SJacky Wang             "import dagger.Component;",
1043*f585d8a3SJacky Wang             "",
1044*f585d8a3SJacky Wang             "@Component",
1045*f585d8a3SJacky Wang             "interface Parent {",
1046*f585d8a3SJacky Wang             "  Child1 getChild1();",
1047*f585d8a3SJacky Wang             "  Child2 getChild2();",
1048*f585d8a3SJacky Wang             "}");
1049*f585d8a3SJacky Wang     Source child1 =
1050*f585d8a3SJacky Wang         CompilerTests.javaSource(
1051*f585d8a3SJacky Wang             "test.Child1",
1052*f585d8a3SJacky Wang             "package test;",
1053*f585d8a3SJacky Wang             "",
1054*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1055*f585d8a3SJacky Wang             "",
1056*f585d8a3SJacky Wang             "@Subcomponent",
1057*f585d8a3SJacky Wang             "interface Child1 {",
1058*f585d8a3SJacky Wang             "  Object getObject();",
1059*f585d8a3SJacky Wang             "}");
1060*f585d8a3SJacky Wang     Source child2 =
1061*f585d8a3SJacky Wang         CompilerTests.javaSource(
1062*f585d8a3SJacky Wang             "test.Child2",
1063*f585d8a3SJacky Wang             "package test;",
1064*f585d8a3SJacky Wang             "",
1065*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1066*f585d8a3SJacky Wang             "",
1067*f585d8a3SJacky Wang             "@Subcomponent(modules = Child2Module.class)",
1068*f585d8a3SJacky Wang             "interface Child2 {}");
1069*f585d8a3SJacky Wang     Source child2Module =
1070*f585d8a3SJacky Wang         CompilerTests.javaSource(
1071*f585d8a3SJacky Wang             "test.Child2Module",
1072*f585d8a3SJacky Wang             "package test;",
1073*f585d8a3SJacky Wang             "",
1074*f585d8a3SJacky Wang             "import dagger.Module;",
1075*f585d8a3SJacky Wang             "import dagger.Provides;",
1076*f585d8a3SJacky Wang             "",
1077*f585d8a3SJacky Wang             "@Module",
1078*f585d8a3SJacky Wang             "interface Child2Module {",
1079*f585d8a3SJacky Wang             "  @Provides",
1080*f585d8a3SJacky Wang             "  static Object provideObject() {",
1081*f585d8a3SJacky Wang             "    return new Object();",
1082*f585d8a3SJacky Wang             "  }",
1083*f585d8a3SJacky Wang             "}");
1084*f585d8a3SJacky Wang 
1085*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(parent, child1, child2, child2Module)
1086*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1087*f585d8a3SJacky Wang         .compile(
1088*f585d8a3SJacky Wang             subject -> {
1089*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1090*f585d8a3SJacky Wang               subject.hasErrorContaining(
1091*f585d8a3SJacky Wang                   String.join(
1092*f585d8a3SJacky Wang                       "\n",
1093*f585d8a3SJacky Wang                       "Object cannot be provided without an @Inject constructor or an "
1094*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
1095*f585d8a3SJacky Wang                       "",
1096*f585d8a3SJacky Wang                       "    Object is requested at",
1097*f585d8a3SJacky Wang                       "        [Child1] Child1.getObject() [Parent → Child1]",
1098*f585d8a3SJacky Wang                       "",
1099*f585d8a3SJacky Wang                       "Note: Object is provided in the following other components:",
1100*f585d8a3SJacky Wang                       "    [Child2] Child2Module.provideObject()"));
1101*f585d8a3SJacky Wang             });
1102*f585d8a3SJacky Wang   }
1103*f585d8a3SJacky Wang 
1104*f585d8a3SJacky Wang   @Test
sameSubcomponentUsedInDifferentHierarchiesMissingBindingFromOneSide()1105*f585d8a3SJacky Wang   public void sameSubcomponentUsedInDifferentHierarchiesMissingBindingFromOneSide() {
1106*f585d8a3SJacky Wang     Source parent =
1107*f585d8a3SJacky Wang         CompilerTests.javaSource(
1108*f585d8a3SJacky Wang             "test.Parent",
1109*f585d8a3SJacky Wang             "package test;",
1110*f585d8a3SJacky Wang             "",
1111*f585d8a3SJacky Wang             "import dagger.Component;",
1112*f585d8a3SJacky Wang             "",
1113*f585d8a3SJacky Wang             "@Component",
1114*f585d8a3SJacky Wang             "interface Parent {",
1115*f585d8a3SJacky Wang             "  Child1 getChild1();",
1116*f585d8a3SJacky Wang             "  Child2 getChild2();",
1117*f585d8a3SJacky Wang             "}");
1118*f585d8a3SJacky Wang     Source child1 =
1119*f585d8a3SJacky Wang         CompilerTests.javaSource(
1120*f585d8a3SJacky Wang             "test.Child1",
1121*f585d8a3SJacky Wang             "package test;",
1122*f585d8a3SJacky Wang             "",
1123*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1124*f585d8a3SJacky Wang             "",
1125*f585d8a3SJacky Wang             "@Subcomponent(modules = Child1Module.class)",
1126*f585d8a3SJacky Wang             "interface Child1 {",
1127*f585d8a3SJacky Wang             "  RepeatedSub getSub();",
1128*f585d8a3SJacky Wang             "}");
1129*f585d8a3SJacky Wang     Source child2 =
1130*f585d8a3SJacky Wang         CompilerTests.javaSource(
1131*f585d8a3SJacky Wang             "test.Child2",
1132*f585d8a3SJacky Wang             "package test;",
1133*f585d8a3SJacky Wang             "",
1134*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1135*f585d8a3SJacky Wang             "",
1136*f585d8a3SJacky Wang             "@Subcomponent(modules = Child2Module.class)",
1137*f585d8a3SJacky Wang             "interface Child2 {",
1138*f585d8a3SJacky Wang             "  RepeatedSub getSub();",
1139*f585d8a3SJacky Wang             "}");
1140*f585d8a3SJacky Wang     Source repeatedSub =
1141*f585d8a3SJacky Wang         CompilerTests.javaSource(
1142*f585d8a3SJacky Wang             "test.RepeatedSub",
1143*f585d8a3SJacky Wang             "package test;",
1144*f585d8a3SJacky Wang             "",
1145*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1146*f585d8a3SJacky Wang             "",
1147*f585d8a3SJacky Wang             "@Subcomponent(modules = RepeatedSubModule.class)",
1148*f585d8a3SJacky Wang             "interface RepeatedSub {",
1149*f585d8a3SJacky Wang             "  Object getObject();",
1150*f585d8a3SJacky Wang             "}");
1151*f585d8a3SJacky Wang     Source child1Module =
1152*f585d8a3SJacky Wang         CompilerTests.javaSource(
1153*f585d8a3SJacky Wang             "test.Child1Module",
1154*f585d8a3SJacky Wang             "package test;",
1155*f585d8a3SJacky Wang             "",
1156*f585d8a3SJacky Wang             "import dagger.Module;",
1157*f585d8a3SJacky Wang             "import dagger.Provides;",
1158*f585d8a3SJacky Wang             "import java.util.Set;",
1159*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1160*f585d8a3SJacky Wang             "",
1161*f585d8a3SJacky Wang             "@Module",
1162*f585d8a3SJacky Wang             "interface Child1Module {",
1163*f585d8a3SJacky Wang             "  @Multibinds Set<Integer> multibindIntegerSet();",
1164*f585d8a3SJacky Wang             "}");
1165*f585d8a3SJacky Wang     Source child2Module =
1166*f585d8a3SJacky Wang         CompilerTests.javaSource(
1167*f585d8a3SJacky Wang             "test.Child2Module",
1168*f585d8a3SJacky Wang             "package test;",
1169*f585d8a3SJacky Wang             "",
1170*f585d8a3SJacky Wang             "import dagger.Module;",
1171*f585d8a3SJacky Wang             "import dagger.Provides;",
1172*f585d8a3SJacky Wang             "import java.util.Set;",
1173*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1174*f585d8a3SJacky Wang             "",
1175*f585d8a3SJacky Wang             "@Module",
1176*f585d8a3SJacky Wang             "interface Child2Module {",
1177*f585d8a3SJacky Wang             "  @Multibinds Set<Integer> multibindIntegerSet();",
1178*f585d8a3SJacky Wang             "",
1179*f585d8a3SJacky Wang             "  @Provides",
1180*f585d8a3SJacky Wang             "  static Object provideObject(Set<Integer> intSet) {",
1181*f585d8a3SJacky Wang             "    return new Object();",
1182*f585d8a3SJacky Wang             "  }",
1183*f585d8a3SJacky Wang             "}");
1184*f585d8a3SJacky Wang     Source repeatedSubModule =
1185*f585d8a3SJacky Wang         CompilerTests.javaSource(
1186*f585d8a3SJacky Wang             "test.RepeatedSubModule",
1187*f585d8a3SJacky Wang             "package test;",
1188*f585d8a3SJacky Wang             "",
1189*f585d8a3SJacky Wang             "import dagger.Module;",
1190*f585d8a3SJacky Wang             "import dagger.Provides;",
1191*f585d8a3SJacky Wang             "import dagger.multibindings.IntoSet;",
1192*f585d8a3SJacky Wang             "import java.util.Set;",
1193*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1194*f585d8a3SJacky Wang             "",
1195*f585d8a3SJacky Wang             "@Module",
1196*f585d8a3SJacky Wang             "interface RepeatedSubModule {",
1197*f585d8a3SJacky Wang             "  @Provides",
1198*f585d8a3SJacky Wang             "  @IntoSet",
1199*f585d8a3SJacky Wang             "  static Integer provideInt() {",
1200*f585d8a3SJacky Wang             "    return 9;",
1201*f585d8a3SJacky Wang             "  }",
1202*f585d8a3SJacky Wang             "}");
1203*f585d8a3SJacky Wang 
1204*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(
1205*f585d8a3SJacky Wang             parent, child1, child2, repeatedSub, child1Module, child2Module, repeatedSubModule)
1206*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1207*f585d8a3SJacky Wang         .compile(
1208*f585d8a3SJacky Wang             subject -> {
1209*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1210*f585d8a3SJacky Wang               subject.hasErrorContaining(
1211*f585d8a3SJacky Wang                   String.join(
1212*f585d8a3SJacky Wang                       "\n",
1213*f585d8a3SJacky Wang                       "Object cannot be provided without an @Inject constructor or an "
1214*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
1215*f585d8a3SJacky Wang                       "",
1216*f585d8a3SJacky Wang                       "    Object is requested at",
1217*f585d8a3SJacky Wang                       "        [RepeatedSub] RepeatedSub.getObject() "
1218*f585d8a3SJacky Wang                           + "[Parent → Child1 → RepeatedSub]",
1219*f585d8a3SJacky Wang                       "",
1220*f585d8a3SJacky Wang                       "Note: Object is provided in the following other components:",
1221*f585d8a3SJacky Wang                       "    [Child2] Child2Module.provideObject(…)"));
1222*f585d8a3SJacky Wang             });
1223*f585d8a3SJacky Wang   }
1224*f585d8a3SJacky Wang 
1225*f585d8a3SJacky Wang   @Test
differentComponentPkgSameSimpleNameMissingBinding()1226*f585d8a3SJacky Wang   public void differentComponentPkgSameSimpleNameMissingBinding() {
1227*f585d8a3SJacky Wang     Source parent =
1228*f585d8a3SJacky Wang         CompilerTests.javaSource(
1229*f585d8a3SJacky Wang             "test.Parent",
1230*f585d8a3SJacky Wang             "package test;",
1231*f585d8a3SJacky Wang             "",
1232*f585d8a3SJacky Wang             "import dagger.Component;",
1233*f585d8a3SJacky Wang             "",
1234*f585d8a3SJacky Wang             "@Component",
1235*f585d8a3SJacky Wang             "interface Parent {",
1236*f585d8a3SJacky Wang             "  Child1 getChild1();",
1237*f585d8a3SJacky Wang             "  Child2 getChild2();",
1238*f585d8a3SJacky Wang             "}");
1239*f585d8a3SJacky Wang     Source child1 =
1240*f585d8a3SJacky Wang         CompilerTests.javaSource(
1241*f585d8a3SJacky Wang             "test.Child1",
1242*f585d8a3SJacky Wang             "package test;",
1243*f585d8a3SJacky Wang             "",
1244*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1245*f585d8a3SJacky Wang             "",
1246*f585d8a3SJacky Wang             "@Subcomponent(modules = Child1Module.class)",
1247*f585d8a3SJacky Wang             "interface Child1 {",
1248*f585d8a3SJacky Wang             "  foo.Sub getSub();",
1249*f585d8a3SJacky Wang             "}");
1250*f585d8a3SJacky Wang     Source child2 =
1251*f585d8a3SJacky Wang         CompilerTests.javaSource(
1252*f585d8a3SJacky Wang             "test.Child2",
1253*f585d8a3SJacky Wang             "package test;",
1254*f585d8a3SJacky Wang             "",
1255*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1256*f585d8a3SJacky Wang             "",
1257*f585d8a3SJacky Wang             "@Subcomponent(modules = Child2Module.class)",
1258*f585d8a3SJacky Wang             "interface Child2 {",
1259*f585d8a3SJacky Wang             "  bar.Sub getSub();",
1260*f585d8a3SJacky Wang             "}");
1261*f585d8a3SJacky Wang     Source sub1 =
1262*f585d8a3SJacky Wang         CompilerTests.javaSource(
1263*f585d8a3SJacky Wang             "foo.Sub",
1264*f585d8a3SJacky Wang             "package foo;",
1265*f585d8a3SJacky Wang             "",
1266*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1267*f585d8a3SJacky Wang             "",
1268*f585d8a3SJacky Wang             "@Subcomponent(modules = test.RepeatedSubModule.class)",
1269*f585d8a3SJacky Wang             "public interface Sub {",
1270*f585d8a3SJacky Wang             "  Object getObject();",
1271*f585d8a3SJacky Wang             "}");
1272*f585d8a3SJacky Wang     Source sub2 =
1273*f585d8a3SJacky Wang         CompilerTests.javaSource(
1274*f585d8a3SJacky Wang             "bar.Sub",
1275*f585d8a3SJacky Wang             "package bar;",
1276*f585d8a3SJacky Wang             "",
1277*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1278*f585d8a3SJacky Wang             "",
1279*f585d8a3SJacky Wang             "@Subcomponent(modules = test.RepeatedSubModule.class)",
1280*f585d8a3SJacky Wang             "public interface Sub {",
1281*f585d8a3SJacky Wang             "  Object getObject();",
1282*f585d8a3SJacky Wang             "}");
1283*f585d8a3SJacky Wang     Source child1Module =
1284*f585d8a3SJacky Wang         CompilerTests.javaSource(
1285*f585d8a3SJacky Wang             "test.Child1Module",
1286*f585d8a3SJacky Wang             "package test;",
1287*f585d8a3SJacky Wang             "",
1288*f585d8a3SJacky Wang             "import dagger.Module;",
1289*f585d8a3SJacky Wang             "import dagger.Provides;",
1290*f585d8a3SJacky Wang             "import java.util.Set;",
1291*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1292*f585d8a3SJacky Wang             "",
1293*f585d8a3SJacky Wang             "@Module",
1294*f585d8a3SJacky Wang             "interface Child1Module {",
1295*f585d8a3SJacky Wang             "  @Multibinds Set<Integer> multibindIntegerSet();",
1296*f585d8a3SJacky Wang             "}");
1297*f585d8a3SJacky Wang     Source child2Module =
1298*f585d8a3SJacky Wang         CompilerTests.javaSource(
1299*f585d8a3SJacky Wang             "test.Child2Module",
1300*f585d8a3SJacky Wang             "package test;",
1301*f585d8a3SJacky Wang             "",
1302*f585d8a3SJacky Wang             "import dagger.Module;",
1303*f585d8a3SJacky Wang             "import dagger.Provides;",
1304*f585d8a3SJacky Wang             "import java.util.Set;",
1305*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1306*f585d8a3SJacky Wang             "",
1307*f585d8a3SJacky Wang             "@Module",
1308*f585d8a3SJacky Wang             "interface Child2Module {",
1309*f585d8a3SJacky Wang             "  @Multibinds Set<Integer> multibindIntegerSet();",
1310*f585d8a3SJacky Wang             "",
1311*f585d8a3SJacky Wang             "  @Provides",
1312*f585d8a3SJacky Wang             "  static Object provideObject(Set<Integer> intSet) {",
1313*f585d8a3SJacky Wang             "    return new Object();",
1314*f585d8a3SJacky Wang             "  }",
1315*f585d8a3SJacky Wang             "}");
1316*f585d8a3SJacky Wang     Source repeatedSubModule =
1317*f585d8a3SJacky Wang         CompilerTests.javaSource(
1318*f585d8a3SJacky Wang             "test.RepeatedSubModule",
1319*f585d8a3SJacky Wang             "package test;",
1320*f585d8a3SJacky Wang             "",
1321*f585d8a3SJacky Wang             "import dagger.Module;",
1322*f585d8a3SJacky Wang             "import dagger.Provides;",
1323*f585d8a3SJacky Wang             "import dagger.multibindings.IntoSet;",
1324*f585d8a3SJacky Wang             "import java.util.Set;",
1325*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
1326*f585d8a3SJacky Wang             "",
1327*f585d8a3SJacky Wang             "@Module",
1328*f585d8a3SJacky Wang             "public interface RepeatedSubModule {",
1329*f585d8a3SJacky Wang             "  @Provides",
1330*f585d8a3SJacky Wang             "  @IntoSet",
1331*f585d8a3SJacky Wang             "  static Integer provideInt() {",
1332*f585d8a3SJacky Wang             "    return 9;",
1333*f585d8a3SJacky Wang             "  }",
1334*f585d8a3SJacky Wang             "}");
1335*f585d8a3SJacky Wang 
1336*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(
1337*f585d8a3SJacky Wang             parent, child1, child2, sub1, sub2, child1Module, child2Module, repeatedSubModule)
1338*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1339*f585d8a3SJacky Wang         .compile(
1340*f585d8a3SJacky Wang             subject -> {
1341*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1342*f585d8a3SJacky Wang               subject.hasErrorContaining(
1343*f585d8a3SJacky Wang                   String.join(
1344*f585d8a3SJacky Wang                       "\n",
1345*f585d8a3SJacky Wang                       "Object cannot be provided without an @Inject constructor or an "
1346*f585d8a3SJacky Wang                           + "@Provides-annotated method.",
1347*f585d8a3SJacky Wang                       "",
1348*f585d8a3SJacky Wang                       "    Object is requested at",
1349*f585d8a3SJacky Wang                       "        [Sub] Sub.getObject() [Parent → Child1 → Sub]",
1350*f585d8a3SJacky Wang                       "",
1351*f585d8a3SJacky Wang                       "Note: Object is provided in the following other components:",
1352*f585d8a3SJacky Wang                       "    [Child2] Child2Module.provideObject(…)"));
1353*f585d8a3SJacky Wang             });
1354*f585d8a3SJacky Wang   }
1355*f585d8a3SJacky Wang 
1356*f585d8a3SJacky Wang   @Test
requestWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding()1357*f585d8a3SJacky Wang   public void requestWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding() {
1358*f585d8a3SJacky Wang     Source component =
1359*f585d8a3SJacky Wang         CompilerTests.javaSource(
1360*f585d8a3SJacky Wang             "test.MyComponent",
1361*f585d8a3SJacky Wang             "package test;",
1362*f585d8a3SJacky Wang             "",
1363*f585d8a3SJacky Wang             "import dagger.Component;",
1364*f585d8a3SJacky Wang             "import java.util.Set;",
1365*f585d8a3SJacky Wang             "",
1366*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1367*f585d8a3SJacky Wang             "interface MyComponent {",
1368*f585d8a3SJacky Wang             "  Foo getFoo();",
1369*f585d8a3SJacky Wang             "  Child getChild();",
1370*f585d8a3SJacky Wang             "}");
1371*f585d8a3SJacky Wang     Source child =
1372*f585d8a3SJacky Wang         CompilerTests.javaSource(
1373*f585d8a3SJacky Wang             "test.Child",
1374*f585d8a3SJacky Wang             "package test;",
1375*f585d8a3SJacky Wang             "",
1376*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
1377*f585d8a3SJacky Wang             "",
1378*f585d8a3SJacky Wang             "@Subcomponent(modules = ChildModule.class)",
1379*f585d8a3SJacky Wang             "interface Child {}");
1380*f585d8a3SJacky Wang     Source childModule =
1381*f585d8a3SJacky Wang         CompilerTests.javaSource(
1382*f585d8a3SJacky Wang             "test.ChildModule",
1383*f585d8a3SJacky Wang             "package test;",
1384*f585d8a3SJacky Wang             "",
1385*f585d8a3SJacky Wang             "import dagger.Module;",
1386*f585d8a3SJacky Wang             "import dagger.Provides;",
1387*f585d8a3SJacky Wang             "import java.util.Set;",
1388*f585d8a3SJacky Wang             "import java.util.HashSet;",
1389*f585d8a3SJacky Wang             "",
1390*f585d8a3SJacky Wang             "@Module",
1391*f585d8a3SJacky Wang             "interface ChildModule {",
1392*f585d8a3SJacky Wang             "  @Provides",
1393*f585d8a3SJacky Wang             "  static Set<? extends Bar> provideBar() {",
1394*f585d8a3SJacky Wang             "    return new HashSet<Bar>();",
1395*f585d8a3SJacky Wang             "  }",
1396*f585d8a3SJacky Wang             "}");
1397*f585d8a3SJacky Wang     Source fooSrc =
1398*f585d8a3SJacky Wang         CompilerTests.javaSource(
1399*f585d8a3SJacky Wang             "test.Foo",
1400*f585d8a3SJacky Wang             "package test;",
1401*f585d8a3SJacky Wang             "",
1402*f585d8a3SJacky Wang             "import javax.inject.Inject;",
1403*f585d8a3SJacky Wang             "import java.util.Set;",
1404*f585d8a3SJacky Wang             "",
1405*f585d8a3SJacky Wang             "class Foo {",
1406*f585d8a3SJacky Wang             "  @Inject Foo(Set<? extends Bar> bar) {}",
1407*f585d8a3SJacky Wang             "}");
1408*f585d8a3SJacky Wang     Source barSrc =
1409*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}");
1410*f585d8a3SJacky Wang     Source moduleSrc =
1411*f585d8a3SJacky Wang         CompilerTests.javaSource(
1412*f585d8a3SJacky Wang             "test.TestModule",
1413*f585d8a3SJacky Wang             "package test;",
1414*f585d8a3SJacky Wang             "",
1415*f585d8a3SJacky Wang             "import dagger.Module;",
1416*f585d8a3SJacky Wang             "import dagger.Provides;",
1417*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet;",
1418*f585d8a3SJacky Wang             "import java.util.Set;",
1419*f585d8a3SJacky Wang             "import java.util.HashSet;",
1420*f585d8a3SJacky Wang             "",
1421*f585d8a3SJacky Wang             "@Module",
1422*f585d8a3SJacky Wang             "public class TestModule {",
1423*f585d8a3SJacky Wang             "   @ElementsIntoSet",
1424*f585d8a3SJacky Wang             "   @Provides",
1425*f585d8a3SJacky Wang             "   Set<Bar> provideBars() {",
1426*f585d8a3SJacky Wang             "     return new HashSet<Bar>();",
1427*f585d8a3SJacky Wang             "   }",
1428*f585d8a3SJacky Wang             "}");
1429*f585d8a3SJacky Wang 
1430*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, child, childModule, fooSrc, barSrc, moduleSrc)
1431*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1432*f585d8a3SJacky Wang         .compile(
1433*f585d8a3SJacky Wang             subject -> {
1434*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1435*f585d8a3SJacky Wang               subject
1436*f585d8a3SJacky Wang                   .hasErrorContaining(
1437*f585d8a3SJacky Wang                       String.join(
1438*f585d8a3SJacky Wang                           "\n",
1439*f585d8a3SJacky Wang                           "Set<? extends Bar> cannot be provided without an @Provides-annotated "
1440*f585d8a3SJacky Wang                               + "method.",
1441*f585d8a3SJacky Wang                           "",
1442*f585d8a3SJacky Wang                           "    Set<? extends Bar> is injected at",
1443*f585d8a3SJacky Wang                           "        [MyComponent] Foo(bar)",
1444*f585d8a3SJacky Wang                           "    Foo is requested at",
1445*f585d8a3SJacky Wang                           "        [MyComponent] MyComponent.getFoo()",
1446*f585d8a3SJacky Wang                           "",
1447*f585d8a3SJacky Wang                           "Note: Set<? extends Bar> is provided in the following other components:",
1448*f585d8a3SJacky Wang                           "    [Child] ChildModule.provideBar()",
1449*f585d8a3SJacky Wang                           "",
1450*f585d8a3SJacky Wang                           "Note: A similar binding is provided in the following other components:",
1451*f585d8a3SJacky Wang                           "    Set<Bar> is provided at:",
1452*f585d8a3SJacky Wang                           "        [MyComponent] Dagger-generated binding for Set<Bar>"))
1453*f585d8a3SJacky Wang                   .onSource(component)
1454*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
1455*f585d8a3SJacky Wang             });
1456*f585d8a3SJacky Wang   }
1457*f585d8a3SJacky Wang 
1458*f585d8a3SJacky Wang   @Test
1459*f585d8a3SJacky Wang   public void
injectParameterDoesNotSuppressWildcardGeneration_conflictsWithNonWildcardTypeBinding()1460*f585d8a3SJacky Wang       injectParameterDoesNotSuppressWildcardGeneration_conflictsWithNonWildcardTypeBinding() {
1461*f585d8a3SJacky Wang     Source component =
1462*f585d8a3SJacky Wang         CompilerTests.javaSource(
1463*f585d8a3SJacky Wang             "test.MyComponent",
1464*f585d8a3SJacky Wang             "package test;",
1465*f585d8a3SJacky Wang             "",
1466*f585d8a3SJacky Wang             "import dagger.Component;",
1467*f585d8a3SJacky Wang             "import java.util.Set;",
1468*f585d8a3SJacky Wang             "",
1469*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1470*f585d8a3SJacky Wang             "interface MyComponent {",
1471*f585d8a3SJacky Wang             "  Foo getFoo();",
1472*f585d8a3SJacky Wang             "}");
1473*f585d8a3SJacky Wang     Source fooSrc =
1474*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1475*f585d8a3SJacky Wang             "Foo.kt",
1476*f585d8a3SJacky Wang             "package test",
1477*f585d8a3SJacky Wang             "",
1478*f585d8a3SJacky Wang             "import javax.inject.Inject",
1479*f585d8a3SJacky Wang             "",
1480*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: Set<Bar>) {}");
1481*f585d8a3SJacky Wang     Source barSrc =
1482*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}");
1483*f585d8a3SJacky Wang     Source moduleSrc =
1484*f585d8a3SJacky Wang         CompilerTests.javaSource(
1485*f585d8a3SJacky Wang             "test.TestModule",
1486*f585d8a3SJacky Wang             "package test;",
1487*f585d8a3SJacky Wang             "",
1488*f585d8a3SJacky Wang             "import dagger.Module;",
1489*f585d8a3SJacky Wang             "import dagger.Provides;",
1490*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet;",
1491*f585d8a3SJacky Wang             "import java.util.Set;",
1492*f585d8a3SJacky Wang             "import java.util.HashSet;",
1493*f585d8a3SJacky Wang             "",
1494*f585d8a3SJacky Wang             "@Module",
1495*f585d8a3SJacky Wang             "public class TestModule {",
1496*f585d8a3SJacky Wang             "   @ElementsIntoSet",
1497*f585d8a3SJacky Wang             "   @Provides",
1498*f585d8a3SJacky Wang             "   Set<Bar> provideBars() {",
1499*f585d8a3SJacky Wang             "     return new HashSet<Bar>();",
1500*f585d8a3SJacky Wang             "   }",
1501*f585d8a3SJacky Wang             "}");
1502*f585d8a3SJacky Wang 
1503*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc)
1504*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1505*f585d8a3SJacky Wang         .compile(
1506*f585d8a3SJacky Wang             subject -> {
1507*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1508*f585d8a3SJacky Wang               subject
1509*f585d8a3SJacky Wang                   .hasErrorContaining(
1510*f585d8a3SJacky Wang                       String.join(
1511*f585d8a3SJacky Wang                           "\n",
1512*f585d8a3SJacky Wang                           "Set<? extends Bar> cannot be provided without an @Provides-annotated "
1513*f585d8a3SJacky Wang                               + "method.",
1514*f585d8a3SJacky Wang                           "",
1515*f585d8a3SJacky Wang                           "    Set<? extends Bar> is injected at",
1516*f585d8a3SJacky Wang                           "        [MyComponent] Foo(bar)",
1517*f585d8a3SJacky Wang                           "    Foo is requested at",
1518*f585d8a3SJacky Wang                           "        [MyComponent] MyComponent.getFoo()",
1519*f585d8a3SJacky Wang                           "",
1520*f585d8a3SJacky Wang                           "Note: A similar binding is provided in the following other components:",
1521*f585d8a3SJacky Wang                           "    Set<Bar> is provided at:",
1522*f585d8a3SJacky Wang                           "        [MyComponent] Dagger-generated binding for Set<Bar>"))
1523*f585d8a3SJacky Wang                   .onSource(component)
1524*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
1525*f585d8a3SJacky Wang             });
1526*f585d8a3SJacky Wang   }
1527*f585d8a3SJacky Wang 
1528*f585d8a3SJacky Wang   @Test
injectWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding()1529*f585d8a3SJacky Wang   public void injectWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding() {
1530*f585d8a3SJacky Wang     Source component =
1531*f585d8a3SJacky Wang         CompilerTests.javaSource(
1532*f585d8a3SJacky Wang             "test.MyComponent",
1533*f585d8a3SJacky Wang             "package test;",
1534*f585d8a3SJacky Wang             "",
1535*f585d8a3SJacky Wang             "import dagger.Component;",
1536*f585d8a3SJacky Wang             "import java.util.Set;",
1537*f585d8a3SJacky Wang             "",
1538*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1539*f585d8a3SJacky Wang             "interface MyComponent {",
1540*f585d8a3SJacky Wang             "  Foo getFoo();",
1541*f585d8a3SJacky Wang             "}");
1542*f585d8a3SJacky Wang     Source fooSrc =
1543*f585d8a3SJacky Wang         CompilerTests.javaSource(
1544*f585d8a3SJacky Wang             "test.Foo",
1545*f585d8a3SJacky Wang             "package test;",
1546*f585d8a3SJacky Wang             "",
1547*f585d8a3SJacky Wang             "import javax.inject.Inject;",
1548*f585d8a3SJacky Wang             "import java.util.Set;",
1549*f585d8a3SJacky Wang             "",
1550*f585d8a3SJacky Wang             "class Foo {",
1551*f585d8a3SJacky Wang             "  @Inject Set<? extends Bar> bar;",
1552*f585d8a3SJacky Wang             "  @Inject Foo() {}",
1553*f585d8a3SJacky Wang             "}");
1554*f585d8a3SJacky Wang     Source barSrc =
1555*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}");
1556*f585d8a3SJacky Wang     Source moduleSrc =
1557*f585d8a3SJacky Wang         CompilerTests.javaSource(
1558*f585d8a3SJacky Wang             "test.TestModule",
1559*f585d8a3SJacky Wang             "package test;",
1560*f585d8a3SJacky Wang             "",
1561*f585d8a3SJacky Wang             "import dagger.Module;",
1562*f585d8a3SJacky Wang             "import dagger.Provides;",
1563*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet;",
1564*f585d8a3SJacky Wang             "import java.util.Set;",
1565*f585d8a3SJacky Wang             "import java.util.HashSet;",
1566*f585d8a3SJacky Wang             "",
1567*f585d8a3SJacky Wang             "@Module",
1568*f585d8a3SJacky Wang             "public class TestModule {",
1569*f585d8a3SJacky Wang             "   @ElementsIntoSet",
1570*f585d8a3SJacky Wang             "   @Provides",
1571*f585d8a3SJacky Wang             "   Set<Bar> provideBars() {",
1572*f585d8a3SJacky Wang             "     return new HashSet<Bar>();",
1573*f585d8a3SJacky Wang             "   }",
1574*f585d8a3SJacky Wang             "}");
1575*f585d8a3SJacky Wang 
1576*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc)
1577*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1578*f585d8a3SJacky Wang         .compile(
1579*f585d8a3SJacky Wang             subject -> {
1580*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1581*f585d8a3SJacky Wang               subject
1582*f585d8a3SJacky Wang                   .hasErrorContaining(
1583*f585d8a3SJacky Wang                       String.join(
1584*f585d8a3SJacky Wang                           "\n",
1585*f585d8a3SJacky Wang                           "Set<? extends Bar> cannot be provided without an @Provides-annotated "
1586*f585d8a3SJacky Wang                               + "method.",
1587*f585d8a3SJacky Wang                           "",
1588*f585d8a3SJacky Wang                           "    Set<? extends Bar> is injected at",
1589*f585d8a3SJacky Wang                           "        [MyComponent] Foo.bar",
1590*f585d8a3SJacky Wang                           "    Foo is requested at",
1591*f585d8a3SJacky Wang                           "        [MyComponent] MyComponent.getFoo()",
1592*f585d8a3SJacky Wang                           "",
1593*f585d8a3SJacky Wang                           "Note: A similar binding is provided in the following other components:",
1594*f585d8a3SJacky Wang                           "    Set<Bar> is provided at:",
1595*f585d8a3SJacky Wang                           "        [MyComponent] Dagger-generated binding for Set<Bar>"))
1596*f585d8a3SJacky Wang                   .onSource(component)
1597*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
1598*f585d8a3SJacky Wang             });
1599*f585d8a3SJacky Wang   }
1600*f585d8a3SJacky Wang 
1601*f585d8a3SJacky Wang   @Test
requestFinalClassWithWildcardAnnotation_missingWildcardTypeBinding()1602*f585d8a3SJacky Wang   public void requestFinalClassWithWildcardAnnotation_missingWildcardTypeBinding() {
1603*f585d8a3SJacky Wang     Source component =
1604*f585d8a3SJacky Wang         CompilerTests.javaSource(
1605*f585d8a3SJacky Wang             "test.MyComponent",
1606*f585d8a3SJacky Wang             "package test;",
1607*f585d8a3SJacky Wang             "",
1608*f585d8a3SJacky Wang             "import dagger.Component;",
1609*f585d8a3SJacky Wang             "import java.util.Set;",
1610*f585d8a3SJacky Wang             "",
1611*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1612*f585d8a3SJacky Wang             "interface MyComponent {",
1613*f585d8a3SJacky Wang             "  Foo getFoo();",
1614*f585d8a3SJacky Wang             "}");
1615*f585d8a3SJacky Wang     Source fooSrc =
1616*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1617*f585d8a3SJacky Wang             "test.Foo.kt",
1618*f585d8a3SJacky Wang             "package test",
1619*f585d8a3SJacky Wang             "",
1620*f585d8a3SJacky Wang             "import javax.inject.Inject",
1621*f585d8a3SJacky Wang             "",
1622*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: List<Bar>) {}");
1623*f585d8a3SJacky Wang     Source barSrc =
1624*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Bar", "package test;", "", "public final class Bar {}");
1625*f585d8a3SJacky Wang     Source moduleSrc =
1626*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1627*f585d8a3SJacky Wang             "test.TestModule.kt",
1628*f585d8a3SJacky Wang             "package test",
1629*f585d8a3SJacky Wang             "",
1630*f585d8a3SJacky Wang             "import dagger.Module",
1631*f585d8a3SJacky Wang             "import dagger.Provides",
1632*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet",
1633*f585d8a3SJacky Wang             "",
1634*f585d8a3SJacky Wang             "@Module",
1635*f585d8a3SJacky Wang             "object TestModule {",
1636*f585d8a3SJacky Wang             "   @Provides fun provideBars(): List<@JvmWildcard Bar> = setOf()",
1637*f585d8a3SJacky Wang             "}");
1638*f585d8a3SJacky Wang 
1639*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc)
1640*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1641*f585d8a3SJacky Wang         .compile(
1642*f585d8a3SJacky Wang             subject -> {
1643*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1644*f585d8a3SJacky Wang               subject
1645*f585d8a3SJacky Wang                   .hasErrorContaining(
1646*f585d8a3SJacky Wang                       String.join(
1647*f585d8a3SJacky Wang                           "\n",
1648*f585d8a3SJacky Wang                           "List<Bar> cannot be provided without an @Provides-annotated method.",
1649*f585d8a3SJacky Wang                           "",
1650*f585d8a3SJacky Wang                           "    List<Bar> is injected at",
1651*f585d8a3SJacky Wang                           "        [MyComponent] Foo(bar)",
1652*f585d8a3SJacky Wang                           "    Foo is requested at",
1653*f585d8a3SJacky Wang                           "        [MyComponent] MyComponent.getFoo()",
1654*f585d8a3SJacky Wang                           "",
1655*f585d8a3SJacky Wang                           "Note: A similar binding is provided in the following other components:",
1656*f585d8a3SJacky Wang                           "    List<? extends Bar> is provided at:",
1657*f585d8a3SJacky Wang                           "        [MyComponent] TestModule.provideBars()"))
1658*f585d8a3SJacky Wang                   .onSource(component)
1659*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
1660*f585d8a3SJacky Wang             });
1661*f585d8a3SJacky Wang   }
1662*f585d8a3SJacky Wang 
1663*f585d8a3SJacky Wang   @Test
multipleTypeParameters_notSuppressWildcardType_failsWithMissingBinding()1664*f585d8a3SJacky Wang   public void multipleTypeParameters_notSuppressWildcardType_failsWithMissingBinding() {
1665*f585d8a3SJacky Wang     Source component =
1666*f585d8a3SJacky Wang         CompilerTests.javaSource(
1667*f585d8a3SJacky Wang             "test.MyComponent",
1668*f585d8a3SJacky Wang             "package test;",
1669*f585d8a3SJacky Wang             "",
1670*f585d8a3SJacky Wang             "import dagger.Component;",
1671*f585d8a3SJacky Wang             "import java.util.Set;",
1672*f585d8a3SJacky Wang             "",
1673*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1674*f585d8a3SJacky Wang             "interface MyComponent {",
1675*f585d8a3SJacky Wang             "  Foo getFoo();",
1676*f585d8a3SJacky Wang             "}");
1677*f585d8a3SJacky Wang     Source fooSrc =
1678*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1679*f585d8a3SJacky Wang             "test.Foo.kt",
1680*f585d8a3SJacky Wang             "package test",
1681*f585d8a3SJacky Wang             "",
1682*f585d8a3SJacky Wang             "import javax.inject.Inject",
1683*f585d8a3SJacky Wang             "",
1684*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: Bar<Baz, Baz, Set<Baz>>) {}");
1685*f585d8a3SJacky Wang     Source barSrc =
1686*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1687*f585d8a3SJacky Wang             "test.Bar.kt", "package test", "", "class Bar<out T1, T2, T3> {}");
1688*f585d8a3SJacky Wang 
1689*f585d8a3SJacky Wang     Source bazSrc =
1690*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Baz", "package test;", "", "public interface Baz {}");
1691*f585d8a3SJacky Wang 
1692*f585d8a3SJacky Wang     Source moduleSrc =
1693*f585d8a3SJacky Wang         CompilerTests.javaSource(
1694*f585d8a3SJacky Wang             "test.TestModule",
1695*f585d8a3SJacky Wang             "package test;",
1696*f585d8a3SJacky Wang             "",
1697*f585d8a3SJacky Wang             "import dagger.Module;",
1698*f585d8a3SJacky Wang             "import dagger.Provides;",
1699*f585d8a3SJacky Wang             "import java.util.Set;",
1700*f585d8a3SJacky Wang             "",
1701*f585d8a3SJacky Wang             "@Module",
1702*f585d8a3SJacky Wang             "public class TestModule {",
1703*f585d8a3SJacky Wang             "   @Provides",
1704*f585d8a3SJacky Wang             "   Bar<Baz, Baz, Set<Baz>> provideBar() {",
1705*f585d8a3SJacky Wang             "     return new Bar<Baz, Baz, Set<Baz>>();",
1706*f585d8a3SJacky Wang             "   }",
1707*f585d8a3SJacky Wang             "}");
1708*f585d8a3SJacky Wang 
1709*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, bazSrc, moduleSrc)
1710*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1711*f585d8a3SJacky Wang         .compile(
1712*f585d8a3SJacky Wang             subject -> {
1713*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1714*f585d8a3SJacky Wang               subject
1715*f585d8a3SJacky Wang                   .hasErrorContaining(
1716*f585d8a3SJacky Wang                       String.join(
1717*f585d8a3SJacky Wang                           "\n",
1718*f585d8a3SJacky Wang                           // TODO(b/324325095): Align KSP and KAPT error message.
1719*f585d8a3SJacky Wang                           CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP
1720*f585d8a3SJacky Wang                               ? "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an "
1721*f585d8a3SJacky Wang                                   + "@Inject constructor or an @Provides-annotated method."
1722*f585d8a3SJacky Wang                               : "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an "
1723*f585d8a3SJacky Wang                                   + "@Provides-annotated method.",
1724*f585d8a3SJacky Wang                           "",
1725*f585d8a3SJacky Wang                           "    Bar<? extends Baz,Baz,Set<Baz>> is injected at",
1726*f585d8a3SJacky Wang                           "        [MyComponent] Foo(bar)",
1727*f585d8a3SJacky Wang                           "    Foo is requested at",
1728*f585d8a3SJacky Wang                           "        [MyComponent] MyComponent.getFoo()",
1729*f585d8a3SJacky Wang                           "",
1730*f585d8a3SJacky Wang                           "Note: A similar binding is provided in the following other components:",
1731*f585d8a3SJacky Wang                           "    Bar<Baz,Baz,Set<Baz>> is provided at:",
1732*f585d8a3SJacky Wang                           "        [MyComponent] TestModule.provideBar()"))
1733*f585d8a3SJacky Wang                   .onSource(component)
1734*f585d8a3SJacky Wang                   .onLineContaining("interface MyComponent");
1735*f585d8a3SJacky Wang             });
1736*f585d8a3SJacky Wang   }
1737*f585d8a3SJacky Wang 
1738*f585d8a3SJacky Wang   @Test
missingBindingWithoutQualifier_warnAboutSimilarTypeWithQualifierExists()1739*f585d8a3SJacky Wang   public void missingBindingWithoutQualifier_warnAboutSimilarTypeWithQualifierExists() {
1740*f585d8a3SJacky Wang     Source qualifierSrc =
1741*f585d8a3SJacky Wang         CompilerTests.javaSource(
1742*f585d8a3SJacky Wang             "test.MyQualifier",
1743*f585d8a3SJacky Wang             "package test;",
1744*f585d8a3SJacky Wang             "",
1745*f585d8a3SJacky Wang             "import javax.inject.Qualifier;",
1746*f585d8a3SJacky Wang             "",
1747*f585d8a3SJacky Wang             "@Qualifier",
1748*f585d8a3SJacky Wang             "@interface MyQualifier {}");
1749*f585d8a3SJacky Wang     Source component =
1750*f585d8a3SJacky Wang         CompilerTests.javaSource(
1751*f585d8a3SJacky Wang             "test.MyComponent",
1752*f585d8a3SJacky Wang             "package test;",
1753*f585d8a3SJacky Wang             "",
1754*f585d8a3SJacky Wang             "import dagger.Component;",
1755*f585d8a3SJacky Wang             "import java.util.Set;",
1756*f585d8a3SJacky Wang             "",
1757*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1758*f585d8a3SJacky Wang             "interface MyComponent {",
1759*f585d8a3SJacky Wang             "  Foo getFoo();",
1760*f585d8a3SJacky Wang             "}");
1761*f585d8a3SJacky Wang     Source fooSrc =
1762*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1763*f585d8a3SJacky Wang             "Foo.kt",
1764*f585d8a3SJacky Wang             "package test",
1765*f585d8a3SJacky Wang             "",
1766*f585d8a3SJacky Wang             "import javax.inject.Inject",
1767*f585d8a3SJacky Wang             "",
1768*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: Set<Bar>) {}");
1769*f585d8a3SJacky Wang     Source barSrc =
1770*f585d8a3SJacky Wang         CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}");
1771*f585d8a3SJacky Wang     Source moduleSrc =
1772*f585d8a3SJacky Wang         CompilerTests.javaSource(
1773*f585d8a3SJacky Wang             "test.TestModule",
1774*f585d8a3SJacky Wang             "package test;",
1775*f585d8a3SJacky Wang             "",
1776*f585d8a3SJacky Wang             "import dagger.Module;",
1777*f585d8a3SJacky Wang             "import dagger.Provides;",
1778*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet;",
1779*f585d8a3SJacky Wang             "import java.util.Set;",
1780*f585d8a3SJacky Wang             "import java.util.HashSet;",
1781*f585d8a3SJacky Wang             "",
1782*f585d8a3SJacky Wang             "@Module",
1783*f585d8a3SJacky Wang             "public class TestModule {",
1784*f585d8a3SJacky Wang             "   @ElementsIntoSet",
1785*f585d8a3SJacky Wang             "   @Provides",
1786*f585d8a3SJacky Wang             "   @MyQualifier",
1787*f585d8a3SJacky Wang             "   Set<Bar> provideBars() {",
1788*f585d8a3SJacky Wang             "     return new HashSet<Bar>();",
1789*f585d8a3SJacky Wang             "   }",
1790*f585d8a3SJacky Wang             "}");
1791*f585d8a3SJacky Wang 
1792*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(qualifierSrc, component, fooSrc, barSrc, moduleSrc)
1793*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1794*f585d8a3SJacky Wang         .compile(
1795*f585d8a3SJacky Wang             subject -> {
1796*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1797*f585d8a3SJacky Wang               subject.hasErrorContaining("MissingBinding");
1798*f585d8a3SJacky Wang               List<DiagnosticMessage> diagnostics =
1799*f585d8a3SJacky Wang                   subject.getCompilationResult().getDiagnostics().get(Diagnostic.Kind.ERROR);
1800*f585d8a3SJacky Wang               assertThat(diagnostics).hasSize(1);
1801*f585d8a3SJacky Wang               assertThat(diagnostics.get(0).getMsg())
1802*f585d8a3SJacky Wang                   .doesNotContain("bindings with similar types exists in the graph");
1803*f585d8a3SJacky Wang             });
1804*f585d8a3SJacky Wang   }
1805*f585d8a3SJacky Wang 
1806*f585d8a3SJacky Wang   @Test
missingWildcardTypeWithObjectBound_providedRawType_warnAboutSimilarTypeExists()1807*f585d8a3SJacky Wang   public void missingWildcardTypeWithObjectBound_providedRawType_warnAboutSimilarTypeExists() {
1808*f585d8a3SJacky Wang     Source component =
1809*f585d8a3SJacky Wang         CompilerTests.javaSource(
1810*f585d8a3SJacky Wang             "test.MyComponent",
1811*f585d8a3SJacky Wang             "package test;",
1812*f585d8a3SJacky Wang             "",
1813*f585d8a3SJacky Wang             "import dagger.Component;",
1814*f585d8a3SJacky Wang             "import java.util.Set;",
1815*f585d8a3SJacky Wang             "",
1816*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1817*f585d8a3SJacky Wang             "interface MyComponent {",
1818*f585d8a3SJacky Wang             "  Foo getFoo();",
1819*f585d8a3SJacky Wang             "}");
1820*f585d8a3SJacky Wang     Source fooSrc =
1821*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1822*f585d8a3SJacky Wang             "test.Foo.kt",
1823*f585d8a3SJacky Wang             "package test",
1824*f585d8a3SJacky Wang             "",
1825*f585d8a3SJacky Wang             "import javax.inject.Inject",
1826*f585d8a3SJacky Wang             "",
1827*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: Bar<Object>) {}");
1828*f585d8a3SJacky Wang     Source barSrc =
1829*f585d8a3SJacky Wang         CompilerTests.kotlinSource("test.Bar.kt", "package test", "", "class Bar<out T1> {}");
1830*f585d8a3SJacky Wang     Source moduleSrc =
1831*f585d8a3SJacky Wang         CompilerTests.javaSource(
1832*f585d8a3SJacky Wang             "test.TestModule",
1833*f585d8a3SJacky Wang             "package test;",
1834*f585d8a3SJacky Wang             "",
1835*f585d8a3SJacky Wang             "import dagger.Module;",
1836*f585d8a3SJacky Wang             "import dagger.Provides;",
1837*f585d8a3SJacky Wang             "import java.util.Set;",
1838*f585d8a3SJacky Wang             "",
1839*f585d8a3SJacky Wang             "@Module",
1840*f585d8a3SJacky Wang             "public class TestModule {",
1841*f585d8a3SJacky Wang             "   @Provides",
1842*f585d8a3SJacky Wang             "   Bar provideBar() {",
1843*f585d8a3SJacky Wang             "     return new Bar<Object>();",
1844*f585d8a3SJacky Wang             "   }",
1845*f585d8a3SJacky Wang             "}");
1846*f585d8a3SJacky Wang 
1847*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc)
1848*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1849*f585d8a3SJacky Wang         .compile(
1850*f585d8a3SJacky Wang             subject -> {
1851*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1852*f585d8a3SJacky Wang               subject.hasErrorContaining(
1853*f585d8a3SJacky Wang                   String.join(
1854*f585d8a3SJacky Wang                       "\n",
1855*f585d8a3SJacky Wang                       // TODO(b/324325095): Align KSP and KAPT error message.
1856*f585d8a3SJacky Wang                       CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP
1857*f585d8a3SJacky Wang                           ? "Bar<?> cannot be provided without an @Inject constructor or an "
1858*f585d8a3SJacky Wang                               + "@Provides-annotated method."
1859*f585d8a3SJacky Wang                           : "Bar<?> cannot be provided without an @Provides-annotated method.",
1860*f585d8a3SJacky Wang                       "",
1861*f585d8a3SJacky Wang                       "    Bar<?> is injected at",
1862*f585d8a3SJacky Wang                       "        [MyComponent] Foo(bar)",
1863*f585d8a3SJacky Wang                       "    Foo is requested at",
1864*f585d8a3SJacky Wang                       "        [MyComponent] MyComponent.getFoo()",
1865*f585d8a3SJacky Wang                       "",
1866*f585d8a3SJacky Wang                       "Note: A similar binding is provided in the following other components:",
1867*f585d8a3SJacky Wang                       "    Bar is provided at:",
1868*f585d8a3SJacky Wang                       "        [MyComponent] TestModule.provideBar()"));
1869*f585d8a3SJacky Wang             });
1870*f585d8a3SJacky Wang   }
1871*f585d8a3SJacky Wang 
1872*f585d8a3SJacky Wang   @Test
missingWildcardType_providedRawType_warnAboutSimilarTypeExists()1873*f585d8a3SJacky Wang   public void missingWildcardType_providedRawType_warnAboutSimilarTypeExists() {
1874*f585d8a3SJacky Wang     Source component =
1875*f585d8a3SJacky Wang         CompilerTests.javaSource(
1876*f585d8a3SJacky Wang             "test.MyComponent",
1877*f585d8a3SJacky Wang             "package test;",
1878*f585d8a3SJacky Wang             "",
1879*f585d8a3SJacky Wang             "import dagger.Component;",
1880*f585d8a3SJacky Wang             "import java.util.Set;",
1881*f585d8a3SJacky Wang             "",
1882*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
1883*f585d8a3SJacky Wang             "interface MyComponent {",
1884*f585d8a3SJacky Wang             "  Foo getFoo();",
1885*f585d8a3SJacky Wang             "}");
1886*f585d8a3SJacky Wang     Source fooSrc =
1887*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
1888*f585d8a3SJacky Wang             "test.Foo.kt",
1889*f585d8a3SJacky Wang             "package test",
1890*f585d8a3SJacky Wang             "",
1891*f585d8a3SJacky Wang             "import javax.inject.Inject",
1892*f585d8a3SJacky Wang             "",
1893*f585d8a3SJacky Wang             "class Foo @Inject constructor(val bar: Bar<String>) {}");
1894*f585d8a3SJacky Wang     Source barSrc =
1895*f585d8a3SJacky Wang         CompilerTests.kotlinSource("test.Bar.kt", "package test", "", "class Bar<out T1> {}");
1896*f585d8a3SJacky Wang     Source moduleSrc =
1897*f585d8a3SJacky Wang         CompilerTests.javaSource(
1898*f585d8a3SJacky Wang             "test.TestModule",
1899*f585d8a3SJacky Wang             "package test;",
1900*f585d8a3SJacky Wang             "",
1901*f585d8a3SJacky Wang             "import dagger.Module;",
1902*f585d8a3SJacky Wang             "import dagger.Provides;",
1903*f585d8a3SJacky Wang             "import java.util.Set;",
1904*f585d8a3SJacky Wang             "",
1905*f585d8a3SJacky Wang             "@Module",
1906*f585d8a3SJacky Wang             "public class TestModule {",
1907*f585d8a3SJacky Wang             "   @Provides",
1908*f585d8a3SJacky Wang             "   Bar provideBar() {",
1909*f585d8a3SJacky Wang             "     return new Bar<Object>();",
1910*f585d8a3SJacky Wang             "   }",
1911*f585d8a3SJacky Wang             "}");
1912*f585d8a3SJacky Wang 
1913*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc)
1914*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
1915*f585d8a3SJacky Wang         .compile(
1916*f585d8a3SJacky Wang             subject -> {
1917*f585d8a3SJacky Wang               subject.hasErrorCount(1);
1918*f585d8a3SJacky Wang               subject.hasErrorContaining("MissingBinding");
1919*f585d8a3SJacky Wang               List<DiagnosticMessage> diagnostics =
1920*f585d8a3SJacky Wang                   subject.getCompilationResult().getDiagnostics().get(Diagnostic.Kind.ERROR);
1921*f585d8a3SJacky Wang               assertThat(diagnostics).hasSize(1);
1922*f585d8a3SJacky Wang               assertThat(diagnostics.get(0).getMsg())
1923*f585d8a3SJacky Wang                   .doesNotContain("bindings with similar types exists in the graph");
1924*f585d8a3SJacky Wang             });
1925*f585d8a3SJacky Wang   }
1926*f585d8a3SJacky Wang }
1927