• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.internal.codegen;
18 
19 import static com.google.common.truth.Truth.assertAbout;
20 import static com.google.testing.compile.CompilationSubject.assertThat;
21 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
22 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
23 import static dagger.internal.codegen.Compilers.compilerWithOptions;
24 import static dagger.internal.codegen.Compilers.daggerCompiler;
25 
26 import com.google.common.collect.ImmutableList;
27 import com.google.testing.compile.Compilation;
28 import com.google.testing.compile.JavaFileObjects;
29 import javax.tools.JavaFileObject;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.JUnit4;
33 
34 @RunWith(JUnit4.class)
35 // TODO(gak): add tests for generation in the default package.
36 public final class InjectConstructorFactoryGeneratorTest {
37   private static final JavaFileObject QUALIFIER_A =
38       JavaFileObjects.forSourceLines("test.QualifierA",
39           "package test;",
40           "",
41           "import javax.inject.Qualifier;",
42           "",
43           "@Qualifier @interface QualifierA {}");
44   private static final JavaFileObject QUALIFIER_B =
45       JavaFileObjects.forSourceLines("test.QualifierB",
46           "package test;",
47           "",
48           "import javax.inject.Qualifier;",
49           "",
50           "@Qualifier @interface QualifierB {}");
51   private static final JavaFileObject SCOPE_A =
52       JavaFileObjects.forSourceLines("test.ScopeA",
53           "package test;",
54           "",
55           "import javax.inject.Scope;",
56           "",
57           "@Scope @interface ScopeA {}");
58   private static final JavaFileObject SCOPE_B =
59       JavaFileObjects.forSourceLines("test.ScopeB",
60           "package test;",
61           "",
62           "import javax.inject.Scope;",
63           "",
64           "@Scope @interface ScopeB {}");
65 
injectOnPrivateConstructor()66   @Test public void injectOnPrivateConstructor() {
67     JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateConstructor",
68         "package test;",
69         "",
70         "import javax.inject.Inject;",
71         "",
72         "class PrivateConstructor {",
73         "  @Inject private PrivateConstructor() {}",
74         "}");
75     Compilation compilation = daggerCompiler().compile(file);
76     assertThat(compilation).failed();
77     assertThat(compilation)
78         .hadErrorContaining("Dagger does not support injection into private constructors")
79         .inFile(file)
80         .onLine(6);
81   }
82 
injectConstructorOnInnerClass()83   @Test public void injectConstructorOnInnerClass() {
84     JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
85         "package test;",
86         "",
87         "import javax.inject.Inject;",
88         "",
89         "class OuterClass {",
90         "  class InnerClass {",
91         "    @Inject InnerClass() {}",
92         "  }",
93         "}");
94     Compilation compilation = daggerCompiler().compile(file);
95     assertThat(compilation).failed();
96     assertThat(compilation)
97         .hadErrorContaining(
98             "@Inject constructors are invalid on inner classes. "
99                 + "Did you mean to make the class static?")
100         .inFile(file)
101         .onLine(7);
102   }
103 
injectConstructorOnAbstractClass()104   @Test public void injectConstructorOnAbstractClass() {
105     JavaFileObject file = JavaFileObjects.forSourceLines("test.AbstractClass",
106         "package test;",
107         "",
108         "import javax.inject.Inject;",
109         "",
110         "abstract class AbstractClass {",
111         "  @Inject AbstractClass() {}",
112         "}");
113     Compilation compilation = daggerCompiler().compile(file);
114     assertThat(compilation).failed();
115     assertThat(compilation)
116         .hadErrorContaining("@Inject is nonsense on the constructor of an abstract class")
117         .inFile(file)
118         .onLine(6);
119   }
120 
injectConstructorOnGenericClass()121   @Test public void injectConstructorOnGenericClass() {
122     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
123         "package test;",
124         "",
125         "import javax.inject.Inject;",
126         "",
127         "class GenericClass<T> {",
128         "  @Inject GenericClass(T t) {}",
129         "}");
130     JavaFileObject expected =
131         JavaFileObjects.forSourceLines(
132             "test.GenericClass_Factory",
133             "package test;",
134             "",
135             GeneratedLines.generatedImports(
136                 "import dagger.internal.Factory;",
137                 "import dagger.internal.QualifierMetadata;",
138                 "import dagger.internal.ScopeMetadata;",
139                 "import javax.inject.Provider;"),
140             "",
141             "@ScopeMetadata",
142             "@QualifierMetadata",
143             GeneratedLines.generatedAnnotations(),
144             "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {",
145             "  private final Provider<T> tProvider;",
146             "",
147             "  public GenericClass_Factory(Provider<T> tProvider) {",
148             "    this.tProvider = tProvider;",
149             "  }",
150             "",
151             "  @Override",
152             "  public GenericClass<T> get() {",
153             "    return newInstance(tProvider.get());",
154             "  }",
155             "",
156             "  public static <T> GenericClass_Factory<T> create(Provider<T> tProvider) {",
157             "    return new GenericClass_Factory<T>(tProvider);",
158             "  }",
159             "",
160             "  public static <T> GenericClass<T> newInstance(T t) {",
161             "    return new GenericClass<T>(t);",
162             "  }",
163             "}");
164     assertAbout(javaSource()).that(file)
165         .processedWith(new ComponentProcessor())
166         .compilesWithoutError()
167         .and().generatesSources(expected);
168   }
169 
fieldAndMethodGenerics()170   @Test public void fieldAndMethodGenerics() {
171     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
172         "package test;",
173         "",
174         "import javax.inject.Inject;",
175         "",
176         "class GenericClass<A, B> {",
177         "  @Inject A a;",
178         "",
179         "  @Inject GenericClass() {}",
180         "",
181         " @Inject void register(B b) {}",
182         "}");
183     JavaFileObject expected =
184         JavaFileObjects.forSourceLines(
185             "test.GenericClass_Factory",
186             "package test;",
187             "",
188             GeneratedLines.generatedImports(
189                 "import dagger.internal.Factory;",
190                 "import dagger.internal.QualifierMetadata;",
191                 "import dagger.internal.ScopeMetadata;",
192                 "import javax.inject.Provider;"),
193             "",
194             "@ScopeMetadata",
195             "@QualifierMetadata",
196             GeneratedLines.generatedAnnotations(),
197             "public final class GenericClass_Factory<A, B> implements",
198             "    Factory<GenericClass<A, B>> {",
199             "  private final Provider<A> aProvider;",
200             "  private final Provider<B> bProvider;",
201             "",
202             "  public GenericClass_Factory(",
203             "      Provider<A> aProvider, Provider<B> bProvider) {",
204             "    this.aProvider = aProvider;",
205             "    this.bProvider = bProvider;",
206             "  }",
207             "",
208             "  @Override",
209             "  public GenericClass<A, B> get() {",
210             "    GenericClass<A, B> instance = newInstance();",
211             "    GenericClass_MembersInjector.injectA(instance, aProvider.get());",
212             "    GenericClass_MembersInjector.injectRegister(instance, bProvider.get());",
213             "    return instance;",
214             "  }",
215             "",
216             "  public static <A, B> GenericClass_Factory<A, B> create(",
217             "      Provider<A> aProvider, Provider<B> bProvider) {",
218             "    return new GenericClass_Factory<A, B>(aProvider, bProvider);",
219             "  }",
220             "",
221             "  public static <A, B> GenericClass<A, B> newInstance() {",
222             "    return new GenericClass<A, B>();",
223             "  }",
224             "}");
225     assertAbout(javaSource()).that(file)
226         .processedWith(new ComponentProcessor())
227         .compilesWithoutError()
228         .and().generatesSources(expected);
229   }
230 
genericClassWithNoDependencies()231   @Test public void genericClassWithNoDependencies() {
232     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
233         "package test;",
234         "",
235         "import javax.inject.Inject;",
236         "",
237         "class GenericClass<T> {",
238         "  @Inject GenericClass() {}",
239         "}");
240     JavaFileObject expected =
241         JavaFileObjects.forSourceLines(
242             "test.GenericClass_Factory",
243             "package test;",
244             "",
245             GeneratedLines.generatedImports(
246                 "import dagger.internal.Factory;",
247                 "import dagger.internal.QualifierMetadata;",
248                 "import dagger.internal.ScopeMetadata;"),
249             "",
250             "@ScopeMetadata",
251             "@QualifierMetadata",
252             GeneratedLines.generatedAnnotations(),
253             "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {",
254             "  @Override",
255             "  public GenericClass<T> get() {",
256             "    return newInstance();",
257             "  }",
258             "",
259             "  @SuppressWarnings(\"unchecked\")",
260             "  public static <T> GenericClass_Factory<T> create() {",
261             "    return InstanceHolder.INSTANCE;",
262             "  }",
263             "",
264             "  public static <T> GenericClass<T> newInstance() {",
265             "    return new GenericClass<T>();",
266             "  }",
267             "",
268             "  private static final class InstanceHolder {",
269             "    @SuppressWarnings(\"rawtypes\")",
270             "    private static final GenericClass_Factory INSTANCE = new GenericClass_Factory();",
271             "  }",
272             "}");
273     assertAbout(javaSource()).that(file)
274         .processedWith(new ComponentProcessor())
275         .compilesWithoutError()
276         .and().generatesSources(expected);
277   }
278 
twoGenericTypes()279   @Test public void twoGenericTypes() {
280     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
281         "package test;",
282         "",
283         "import javax.inject.Inject;",
284         "",
285         "class GenericClass<A, B> {",
286         "  @Inject GenericClass(A a, B b) {}",
287         "}");
288     JavaFileObject expected =
289         JavaFileObjects.forSourceLines(
290             "test.GenericClass_Factory",
291             "package test;",
292             "",
293             GeneratedLines.generatedImports(
294                 "import dagger.internal.Factory;",
295                 "import dagger.internal.QualifierMetadata;",
296                 "import dagger.internal.ScopeMetadata;",
297                 "import javax.inject.Provider;"),
298             "",
299             "@ScopeMetadata",
300             "@QualifierMetadata",
301             GeneratedLines.generatedAnnotations(),
302             "public final class GenericClass_Factory<A, B>",
303             "    implements Factory<GenericClass<A, B>> {",
304             "  private final Provider<A> aProvider;",
305             "  private final Provider<B> bProvider;",
306             "",
307             "  public GenericClass_Factory(Provider<A> aProvider, Provider<B> bProvider) {",
308             "    this.aProvider = aProvider;",
309             "    this.bProvider = bProvider;",
310             "  }",
311             "",
312             "  @Override",
313             "  public GenericClass<A, B> get() {",
314             "    return newInstance(aProvider.get(), bProvider.get());",
315             "  }",
316             "",
317             "  public static <A, B> GenericClass_Factory<A, B> create(",
318             "      Provider<A> aProvider, Provider<B> bProvider) {",
319             "    return new GenericClass_Factory<A, B>(aProvider, bProvider);",
320             "  }",
321             "",
322             "  public static <A, B> GenericClass<A, B> newInstance(A a, B b) {",
323             "    return new GenericClass<A, B>(a, b);",
324             "  }",
325             "}");
326     assertAbout(javaSource()).that(file)
327         .processedWith(new ComponentProcessor())
328         .compilesWithoutError()
329         .and().generatesSources(expected);
330   }
331 
boundedGenerics()332   @Test public void boundedGenerics() {
333     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
334         "package test;",
335         "",
336         "import javax.inject.Inject;",
337         "import java.util.List;",
338         "",
339         "class GenericClass<A extends Number & Comparable<A>,",
340         "    B extends List<? extends String>,",
341         "    C extends List<? super String>> {",
342         "  @Inject GenericClass(A a, B b, C c) {}",
343         "}");
344     JavaFileObject expected =
345         JavaFileObjects.forSourceLines(
346             "test.GenericClass_Factory",
347             "package test;",
348             "",
349             GeneratedLines.generatedImports(
350                 "import dagger.internal.Factory;",
351                 "import dagger.internal.QualifierMetadata;",
352                 "import dagger.internal.ScopeMetadata;",
353                 "import java.util.List;",
354                 "import javax.inject.Provider;"),
355             "",
356             "@ScopeMetadata",
357             "@QualifierMetadata",
358             GeneratedLines.generatedAnnotations(),
359             "public final class GenericClass_Factory<A extends Number & Comparable<A>,",
360             "        B extends List<? extends String>,",
361             "        C extends List<? super String>>",
362             "    implements Factory<GenericClass<A, B, C>> {",
363             "  private final Provider<A> aProvider;",
364             "  private final Provider<B> bProvider;",
365             "  private final Provider<C> cProvider;",
366             "",
367             "  public GenericClass_Factory(Provider<A> aProvider,",
368             "      Provider<B> bProvider,",
369             "      Provider<C> cProvider) {",
370             "    this.aProvider = aProvider;",
371             "    this.bProvider = bProvider;",
372             "    this.cProvider = cProvider;",
373             "  }",
374             "",
375             "  @Override",
376             "  public GenericClass<A, B, C> get() {",
377             "    return newInstance(aProvider.get(), bProvider.get(), cProvider.get());",
378             "  }",
379             "",
380             "  public static <A extends Number & Comparable<A>,",
381             "      B extends List<? extends String>,",
382             "      C extends List<? super String>> GenericClass_Factory<A, B, C> create(",
383             "          Provider<A> aProvider, Provider<B> bProvider, Provider<C> cProvider) {",
384             "    return new GenericClass_Factory<A, B, C>(aProvider, bProvider, cProvider);",
385             "  }",
386             "",
387             "  public static <",
388             "          A extends Number & Comparable<A>,",
389             "          B extends List<? extends String>,",
390             "          C extends List<? super String>>",
391             "      GenericClass<A, B, C> newInstance(A a, B b, C c) {",
392             "    return new GenericClass<A, B, C>(a, b, c);",
393             "  }",
394             "}");
395     assertAbout(javaSource()).that(file)
396         .processedWith(new ComponentProcessor())
397         .compilesWithoutError()
398         .and().generatesSources(expected);
399   }
400 
multipleSameTypesWithGenericsAndQualifiersAndLazies()401   @Test public void multipleSameTypesWithGenericsAndQualifiersAndLazies() {
402     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
403         "package test;",
404         "",
405         "import javax.inject.Inject;",
406         "import javax.inject.Provider;",
407         "import dagger.Lazy;",
408         "",
409         "class GenericClass<A, B> {",
410         "  @Inject GenericClass(A a, A a2, Provider<A> pa, @QualifierA A qa, Lazy<A> la, ",
411         "                       String s, String s2, Provider<String> ps, ",
412         "                       @QualifierA String qs, Lazy<String> ls,",
413         "                       B b, B b2, Provider<B> pb, @QualifierA B qb, Lazy<B> lb) {}",
414         "}");
415     JavaFileObject expected =
416         JavaFileObjects.forSourceLines(
417             "test.GenericClass_Factory",
418             "package test;",
419             "",
420             GeneratedLines.generatedImports(
421                 "import dagger.Lazy;",
422                 "import dagger.internal.DoubleCheck;",
423                 "import dagger.internal.Factory;",
424                 "import dagger.internal.QualifierMetadata;",
425                 "import dagger.internal.ScopeMetadata;",
426                 "import javax.inject.Provider;"),
427             "",
428             "@ScopeMetadata",
429             "@QualifierMetadata(\"test.QualifierA\")",
430             GeneratedLines.generatedAnnotations(),
431             "public final class GenericClass_Factory<A, B>",
432             "    implements Factory<GenericClass<A, B>> {",
433             "  private final Provider<A> aProvider;",
434             "  private final Provider<A> a2Provider;",
435             "  private final Provider<A> paProvider;",
436             "  private final Provider<A> qaProvider;",
437             "  private final Provider<A> laProvider;",
438             "  private final Provider<String> sProvider;",
439             "  private final Provider<String> s2Provider;",
440             "  private final Provider<String> psProvider;",
441             "  private final Provider<String> qsProvider;",
442             "  private final Provider<String> lsProvider;",
443             "  private final Provider<B> bProvider;",
444             "  private final Provider<B> b2Provider;",
445             "  private final Provider<B> pbProvider;",
446             "  private final Provider<B> qbProvider;",
447             "  private final Provider<B> lbProvider;",
448             "",
449             "  public GenericClass_Factory(",
450             "      Provider<A> aProvider,",
451             "      Provider<A> a2Provider,",
452             "      Provider<A> paProvider,",
453             "      Provider<A> qaProvider,",
454             "      Provider<A> laProvider,",
455             "      Provider<String> sProvider,",
456             "      Provider<String> s2Provider,",
457             "      Provider<String> psProvider,",
458             "      Provider<String> qsProvider,",
459             "      Provider<String> lsProvider,",
460             "      Provider<B> bProvider,",
461             "      Provider<B> b2Provider,",
462             "      Provider<B> pbProvider,",
463             "      Provider<B> qbProvider,",
464             "      Provider<B> lbProvider) {",
465             "    this.aProvider = aProvider;",
466             "    this.a2Provider = a2Provider;",
467             "    this.paProvider = paProvider;",
468             "    this.qaProvider = qaProvider;",
469             "    this.laProvider = laProvider;",
470             "    this.sProvider = sProvider;",
471             "    this.s2Provider = s2Provider;",
472             "    this.psProvider = psProvider;",
473             "    this.qsProvider = qsProvider;",
474             "    this.lsProvider = lsProvider;",
475             "    this.bProvider = bProvider;",
476             "    this.b2Provider = b2Provider;",
477             "    this.pbProvider = pbProvider;",
478             "    this.qbProvider = qbProvider;",
479             "    this.lbProvider = lbProvider;",
480             "  }",
481             "",
482             "  @Override",
483             "  public GenericClass<A, B> get() {",
484             "    return newInstance(",
485             "        aProvider.get(),",
486             "        a2Provider.get(),",
487             "        paProvider,",
488             "        qaProvider.get(),",
489             "        DoubleCheck.lazy(laProvider),",
490             "        sProvider.get(),",
491             "        s2Provider.get(),",
492             "        psProvider,",
493             "        qsProvider.get(),",
494             "        DoubleCheck.lazy(lsProvider),",
495             "        bProvider.get(),",
496             "        b2Provider.get(),",
497             "        pbProvider,",
498             "        qbProvider.get(),",
499             "        DoubleCheck.lazy(lbProvider));",
500             "  }",
501             "",
502             "  public static <A, B> GenericClass_Factory<A, B> create(",
503             "      Provider<A> aProvider,",
504             "      Provider<A> a2Provider,",
505             "      Provider<A> paProvider,",
506             "      Provider<A> qaProvider,",
507             "      Provider<A> laProvider,",
508             "      Provider<String> sProvider,",
509             "      Provider<String> s2Provider,",
510             "      Provider<String> psProvider,",
511             "      Provider<String> qsProvider,",
512             "      Provider<String> lsProvider,",
513             "      Provider<B> bProvider,",
514             "      Provider<B> b2Provider,",
515             "      Provider<B> pbProvider,",
516             "      Provider<B> qbProvider,",
517             "      Provider<B> lbProvider) {",
518             "    return new GenericClass_Factory<A, B>(",
519             "        aProvider,",
520             "        a2Provider,",
521             "        paProvider,",
522             "        qaProvider,",
523             "        laProvider,",
524             "        sProvider,",
525             "        s2Provider,",
526             "        psProvider,",
527             "        qsProvider,",
528             "        lsProvider,",
529             "        bProvider,",
530             "        b2Provider,",
531             "        pbProvider,",
532             "        qbProvider,",
533             "        lbProvider);",
534             "  }",
535             "",
536             "  public static <A, B> GenericClass<A, B> newInstance(",
537             "      A a,",
538             "      A a2,",
539             "      Provider<A> pa,",
540             "      A qa,",
541             "      Lazy<A> la,",
542             "      String s,",
543             "      String s2,",
544             "      Provider<String> ps,",
545             "      String qs,",
546             "      Lazy<String> ls,",
547             "      B b,",
548             "      B b2,",
549             "      Provider<B> pb,",
550             "      B qb,",
551             "      Lazy<B> lb) {",
552             "    return new GenericClass<A, B>(",
553             "        a, a2, pa, qa, la, s, s2, ps, qs, ls, b, b2, pb, qb, lb);",
554             "  }",
555             "}");
556     assertAbout(javaSources()).that(ImmutableList.of(file, QUALIFIER_A))
557         .processedWith(new ComponentProcessor())
558         .compilesWithoutError()
559         .and().generatesSources(expected);
560   }
561 
multipleInjectConstructors()562   @Test public void multipleInjectConstructors() {
563     JavaFileObject file = JavaFileObjects.forSourceLines("test.TooManyInjectConstructors",
564         "package test;",
565         "",
566         "import javax.inject.Inject;",
567         "",
568         "class TooManyInjectConstructors {",
569         "  @Inject TooManyInjectConstructors() {}",
570         "  TooManyInjectConstructors(int i) {}",
571         "  @Inject TooManyInjectConstructors(String s) {}",
572         "}");
573     Compilation compilation = daggerCompiler().compile(file);
574     assertThat(compilation).failed();
575     assertThat(compilation).hadErrorCount(1);
576     assertThat(compilation)
577         .hadErrorContaining(
578             "Type test.TooManyInjectConstructors may only contain one injected constructor. "
579                 + "Found: ["
580                 + "TooManyInjectConstructors(), "
581                 + "TooManyInjectConstructors(java.lang.String)"
582                 + "]")
583         .inFile(file)
584         .onLine(5);
585   }
586 
multipleQualifiersOnInjectConstructorParameter()587   @Test public void multipleQualifiersOnInjectConstructorParameter() {
588     JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierConstructorParam",
589         "package test;",
590         "",
591         "import javax.inject.Inject;",
592         "",
593         "class MultipleQualifierConstructorParam {",
594         "  @Inject MultipleQualifierConstructorParam(@QualifierA @QualifierB String s) {}",
595         "}");
596     Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B);
597     assertThat(compilation).failed();
598     // for whatever reason, javac only reports the error once on the constructor
599     assertThat(compilation)
600         .hadErrorContaining("A single dependency request may not use more than one @Qualifier")
601         .inFile(file)
602         .onLine(6);
603   }
604 
injectConstructorOnClassWithMultipleScopes()605   @Test public void injectConstructorOnClassWithMultipleScopes() {
606     JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleScopeClass",
607         "package test;",
608         "",
609         "import javax.inject.Inject;",
610         "",
611         "@ScopeA @ScopeB class MultipleScopeClass {",
612         "  @Inject MultipleScopeClass() {}",
613         "}");
614     Compilation compilation = daggerCompiler().compile(file, SCOPE_A, SCOPE_B);
615     assertThat(compilation).failed();
616     assertThat(compilation)
617         .hadErrorContaining("A single binding may not declare more than one @Scope")
618         .inFile(file)
619         .onLine(5)
620         .atColumn(1);
621     assertThat(compilation)
622         .hadErrorContaining("A single binding may not declare more than one @Scope")
623         .inFile(file)
624         .onLine(5)
625         .atColumn(9);
626   }
627 
injectConstructorWithQualifier()628   @Test public void injectConstructorWithQualifier() {
629     JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleScopeClass",
630         "package test;",
631         "",
632         "import javax.inject.Inject;",
633         "",
634         "class MultipleScopeClass {",
635         "  @Inject",
636         "  @QualifierA",
637         "  @QualifierB",
638         "  MultipleScopeClass() {}",
639         "}");
640     Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B);
641     assertThat(compilation).failed();
642     assertThat(compilation)
643         .hadErrorContaining("@Qualifier annotations are not allowed on @Inject constructors")
644         .inFile(file)
645         .onLine(7);
646     assertThat(compilation)
647         .hadErrorContaining("@Qualifier annotations are not allowed on @Inject constructors")
648         .inFile(file)
649         .onLine(8);
650   }
651 
injectConstructorWithCheckedExceptionsError()652   @Test public void injectConstructorWithCheckedExceptionsError() {
653     JavaFileObject file = JavaFileObjects.forSourceLines("test.CheckedExceptionClass",
654         "package test;",
655         "",
656         "import javax.inject.Inject;",
657         "",
658         "class CheckedExceptionClass {",
659         "  @Inject CheckedExceptionClass() throws Exception {}",
660         "}");
661     Compilation compilation = daggerCompiler().compile(file);
662     assertThat(compilation).failed();
663     assertThat(compilation)
664         .hadErrorContaining("Dagger does not support checked exceptions on @Inject constructors")
665         .inFile(file)
666         .onLine(6);
667   }
668 
injectConstructorWithCheckedExceptionsWarning()669   @Test public void injectConstructorWithCheckedExceptionsWarning() {
670     JavaFileObject file = JavaFileObjects.forSourceLines("test.CheckedExceptionClass",
671         "package test;",
672         "",
673         "import javax.inject.Inject;",
674         "",
675         "class CheckedExceptionClass {",
676         "  @Inject CheckedExceptionClass() throws Exception {}",
677         "}");
678     Compilation compilation =
679         compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
680     assertThat(compilation).succeeded();
681     assertThat(compilation)
682         .hadWarningContaining("Dagger does not support checked exceptions on @Inject constructors")
683         .inFile(file)
684         .onLine(6);
685   }
686 
privateInjectClassError()687   @Test public void privateInjectClassError() {
688     JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
689         "package test;",
690         "",
691         "import javax.inject.Inject;",
692         "",
693         "final class OuterClass {",
694         "  private static final class InnerClass {",
695         "    @Inject InnerClass() {}",
696         "  }",
697         "}");
698     Compilation compilation = daggerCompiler().compile(file);
699     assertThat(compilation).failed();
700     assertThat(compilation)
701         .hadErrorContaining("Dagger does not support injection into private classes")
702         .inFile(file)
703         .onLine(7);
704   }
705 
privateInjectClassWarning()706   @Test public void privateInjectClassWarning() {
707     JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
708         "package test;",
709         "",
710         "import javax.inject.Inject;",
711         "",
712         "final class OuterClass {",
713         "  private static final class InnerClass {",
714         "    @Inject InnerClass() {}",
715         "  }",
716         "}");
717     Compilation compilation =
718         compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
719     assertThat(compilation).succeeded();
720     assertThat(compilation)
721         .hadWarningContaining("Dagger does not support injection into private classes")
722         .inFile(file)
723         .onLine(7);
724   }
725 
nestedInPrivateInjectClassError()726   @Test public void nestedInPrivateInjectClassError() {
727     JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
728         "package test;",
729         "",
730         "import javax.inject.Inject;",
731         "",
732         "final class OuterClass {",
733         "  private static final class MiddleClass {",
734         "    static final class InnerClass {",
735         "      @Inject InnerClass() {}",
736         "    }",
737         "  }",
738         "}");
739     Compilation compilation = daggerCompiler().compile(file);
740     assertThat(compilation).failed();
741     assertThat(compilation)
742         .hadErrorContaining("Dagger does not support injection into private classes")
743         .inFile(file)
744         .onLine(8);
745   }
746 
nestedInPrivateInjectClassWarning()747   @Test public void nestedInPrivateInjectClassWarning() {
748     JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
749         "package test;",
750         "",
751         "import javax.inject.Inject;",
752         "",
753         "final class OuterClass {",
754         "  private static final class MiddleClass {",
755         "    static final class InnerClass {",
756         "      @Inject InnerClass() {}",
757         "    }",
758         "  }",
759         "}");
760     Compilation compilation =
761         compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
762     assertThat(compilation).succeeded();
763     assertThat(compilation)
764         .hadWarningContaining("Dagger does not support injection into private classes")
765         .inFile(file)
766         .onLine(8);
767   }
768 
finalInjectField()769   @Test public void finalInjectField() {
770     JavaFileObject file = JavaFileObjects.forSourceLines("test.FinalInjectField",
771         "package test;",
772         "",
773         "import javax.inject.Inject;",
774         "",
775         "class FinalInjectField {",
776         "  @Inject final String s;",
777         "}");
778     Compilation compilation = daggerCompiler().compile(file);
779     assertThat(compilation).failed();
780     assertThat(compilation)
781         .hadErrorContaining("@Inject fields may not be final")
782         .inFile(file)
783         .onLine(6);
784   }
785 
privateInjectFieldError()786   @Test public void privateInjectFieldError() {
787     JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectField",
788         "package test;",
789         "",
790         "import javax.inject.Inject;",
791         "",
792         "class PrivateInjectField {",
793         "  @Inject private String s;",
794         "}");
795     Compilation compilation = daggerCompiler().compile(file);
796     assertThat(compilation).failed();
797     assertThat(compilation)
798         .hadErrorContaining("Dagger does not support injection into private fields")
799         .inFile(file)
800         .onLine(6);
801   }
802 
privateInjectFieldWarning()803   @Test public void privateInjectFieldWarning() {
804     JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectField",
805         "package test;",
806         "",
807         "import javax.inject.Inject;",
808         "",
809         "class PrivateInjectField {",
810         "  @Inject private String s;",
811         "}");
812     Compilation compilation =
813         compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
814     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
815   }
816 
staticInjectFieldError()817   @Test public void staticInjectFieldError() {
818     JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectField",
819         "package test;",
820         "",
821         "import javax.inject.Inject;",
822         "",
823         "class StaticInjectField {",
824         "  @Inject static String s;",
825         "}");
826     Compilation compilation = daggerCompiler().compile(file);
827     assertThat(compilation).failed();
828     assertThat(compilation)
829         .hadErrorContaining("Dagger does not support injection into static fields")
830         .inFile(file)
831         .onLine(6);
832   }
833 
staticInjectFieldWarning()834   @Test public void staticInjectFieldWarning() {
835     JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectField",
836         "package test;",
837         "",
838         "import javax.inject.Inject;",
839         "",
840         "class StaticInjectField {",
841         "  @Inject static String s;",
842         "}");
843     Compilation compilation =
844         compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
845     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
846   }
847 
multipleQualifiersOnField()848   @Test public void multipleQualifiersOnField() {
849     JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierInjectField",
850         "package test;",
851         "",
852         "import javax.inject.Inject;",
853         "",
854         "class MultipleQualifierInjectField {",
855         "  @Inject @QualifierA @QualifierB String s;",
856         "}");
857     Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B);
858     assertThat(compilation).failed();
859     assertThat(compilation)
860         .hadErrorContaining("A single dependency request may not use more than one @Qualifier")
861         .inFile(file)
862         .onLine(6)
863         .atColumn(11);
864     assertThat(compilation)
865         .hadErrorContaining("A single dependency request may not use more than one @Qualifier")
866         .inFile(file)
867         .onLine(6)
868         .atColumn(23);
869   }
870 
abstractInjectMethod()871   @Test public void abstractInjectMethod() {
872     JavaFileObject file = JavaFileObjects.forSourceLines("test.AbstractInjectMethod",
873         "package test;",
874         "",
875         "import javax.inject.Inject;",
876         "",
877         "abstract class AbstractInjectMethod {",
878         "  @Inject abstract void method();",
879         "}");
880     Compilation compilation = daggerCompiler().compile(file);
881     assertThat(compilation).failed();
882     assertThat(compilation)
883         .hadErrorContaining("Methods with @Inject may not be abstract")
884         .inFile(file)
885         .onLine(6);
886   }
887 
privateInjectMethodError()888   @Test public void privateInjectMethodError() {
889     JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectMethod",
890         "package test;",
891         "",
892         "import javax.inject.Inject;",
893         "",
894         "class PrivateInjectMethod {",
895         "  @Inject private void method(){}",
896         "}");
897     Compilation compilation = daggerCompiler().compile(file);
898     assertThat(compilation).failed();
899     assertThat(compilation)
900         .hadErrorContaining("Dagger does not support injection into private methods")
901         .inFile(file)
902         .onLine(6);
903   }
904 
privateInjectMethodWarning()905   @Test public void privateInjectMethodWarning() {
906     JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectMethod",
907         "package test;",
908         "",
909         "import javax.inject.Inject;",
910         "",
911         "class PrivateInjectMethod {",
912         "  @Inject private void method(){}",
913         "}");
914     Compilation compilation =
915         compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
916     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
917   }
918 
staticInjectMethodError()919   @Test public void staticInjectMethodError() {
920     JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectMethod",
921         "package test;",
922         "",
923         "import javax.inject.Inject;",
924         "",
925         "class StaticInjectMethod {",
926         "  @Inject static void method(){}",
927         "}");
928     Compilation compilation = daggerCompiler().compile(file);
929     assertThat(compilation).failed();
930     assertThat(compilation)
931         .hadErrorContaining("Dagger does not support injection into static methods")
932         .inFile(file)
933         .onLine(6);
934   }
935 
staticInjectMethodWarning()936   @Test public void staticInjectMethodWarning() {
937     JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectMethod",
938         "package test;",
939         "",
940         "import javax.inject.Inject;",
941         "",
942         "class StaticInjectMethod {",
943         "  @Inject static void method(){}",
944         "}");
945     Compilation compilation =
946         compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
947     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
948   }
949 
genericInjectMethod()950   @Test public void genericInjectMethod() {
951     JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericInjectMethod",
952         "package test;",
953         "",
954         "import javax.inject.Inject;",
955         "",
956         "class AbstractInjectMethod {",
957         "  @Inject <T> void method();",
958         "}");
959     Compilation compilation = daggerCompiler().compile(file);
960     assertThat(compilation).failed();
961     assertThat(compilation)
962         .hadErrorContaining("Methods with @Inject may not declare type parameters")
963         .inFile(file)
964         .onLine(6);
965   }
966 
multipleQualifiersOnInjectMethodParameter()967   @Test public void multipleQualifiersOnInjectMethodParameter() {
968     JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierMethodParam",
969         "package test;",
970         "",
971         "import javax.inject.Inject;",
972         "",
973         "class MultipleQualifierMethodParam {",
974         "  @Inject void method(@QualifierA @QualifierB String s) {}",
975         "}");
976     Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B);
977     assertThat(compilation).failed();
978     assertThat(compilation)
979         .hadErrorContaining("A single dependency request may not use more than one @Qualifier")
980         .inFile(file)
981         .onLine(6);
982   }
983 
injectConstructorDependsOnProduced()984   @Test public void injectConstructorDependsOnProduced() {
985     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
986         "package test;",
987         "",
988         "import dagger.producers.Produced;",
989         "import javax.inject.Inject;",
990         "",
991         "final class A {",
992         "  @Inject A(Produced<String> str) {}",
993         "}");
994     Compilation compilation = daggerCompiler().compile(aFile);
995     assertThat(compilation).failed();
996     assertThat(compilation)
997         .hadErrorContaining("Produced may only be injected in @Produces methods");
998   }
999 
injectConstructorDependsOnProducer()1000   @Test public void injectConstructorDependsOnProducer() {
1001     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
1002         "package test;",
1003         "",
1004         "import dagger.producers.Producer;",
1005         "import javax.inject.Inject;",
1006         "",
1007         "final class A {",
1008         "  @Inject A(Producer<String> str) {}",
1009         "}");
1010     Compilation compilation = daggerCompiler().compile(aFile);
1011     assertThat(compilation).failed();
1012     assertThat(compilation)
1013         .hadErrorContaining("Producer may only be injected in @Produces methods");
1014   }
1015 
injectFieldDependsOnProduced()1016   @Test public void injectFieldDependsOnProduced() {
1017     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
1018         "package test;",
1019         "",
1020         "import dagger.producers.Produced;",
1021         "import javax.inject.Inject;",
1022         "",
1023         "final class A {",
1024         "  @Inject Produced<String> str;",
1025         "}");
1026     Compilation compilation = daggerCompiler().compile(aFile);
1027     assertThat(compilation).failed();
1028     assertThat(compilation)
1029         .hadErrorContaining("Produced may only be injected in @Produces methods");
1030   }
1031 
injectFieldDependsOnProducer()1032   @Test public void injectFieldDependsOnProducer() {
1033     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
1034         "package test;",
1035         "",
1036         "import dagger.producers.Producer;",
1037         "import javax.inject.Inject;",
1038         "",
1039         "final class A {",
1040         "  @Inject Producer<String> str;",
1041         "}");
1042     Compilation compilation = daggerCompiler().compile(aFile);
1043     assertThat(compilation).failed();
1044     assertThat(compilation)
1045         .hadErrorContaining("Producer may only be injected in @Produces methods");
1046   }
1047 
injectMethodDependsOnProduced()1048   @Test public void injectMethodDependsOnProduced() {
1049     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
1050         "package test;",
1051         "",
1052         "import dagger.producers.Produced;",
1053         "import javax.inject.Inject;",
1054         "",
1055         "final class A {",
1056         "  @Inject void inject(Produced<String> str) {}",
1057         "}");
1058     Compilation compilation = daggerCompiler().compile(aFile);
1059     assertThat(compilation).failed();
1060     assertThat(compilation)
1061         .hadErrorContaining("Produced may only be injected in @Produces methods");
1062   }
1063 
injectMethodDependsOnProducer()1064   @Test public void injectMethodDependsOnProducer() {
1065     JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
1066         "package test;",
1067         "",
1068         "import dagger.producers.Producer;",
1069         "import javax.inject.Inject;",
1070         "",
1071         "final class A {",
1072         "  @Inject void inject(Producer<String> str) {}",
1073         "}");
1074     Compilation compilation = daggerCompiler().compile(aFile);
1075     assertThat(compilation).failed();
1076     assertThat(compilation)
1077         .hadErrorContaining("Producer may only be injected in @Produces methods");
1078   }
1079 
1080 
injectConstructor()1081   @Test public void injectConstructor() {
1082     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
1083         "package test;",
1084         "",
1085         "import javax.inject.Inject;",
1086         "",
1087         "class InjectConstructor {",
1088         "  @Inject InjectConstructor(String s) {}",
1089         "}");
1090     JavaFileObject expected =
1091         JavaFileObjects.forSourceLines(
1092             "test.InjectConstructor_Factory",
1093             "package test;",
1094             "",
1095             GeneratedLines.generatedImports(
1096                 "import dagger.internal.Factory;",
1097                 "import dagger.internal.QualifierMetadata;",
1098                 "import dagger.internal.ScopeMetadata;",
1099                 "import javax.inject.Provider;"),
1100             "",
1101             "@ScopeMetadata",
1102             "@QualifierMetadata",
1103             GeneratedLines.generatedAnnotations(),
1104             "public final class InjectConstructor_Factory ",
1105             "    implements Factory<InjectConstructor> {",
1106             "",
1107             "  private final Provider<String> sProvider;",
1108             "",
1109             "  public InjectConstructor_Factory(Provider<String> sProvider) {",
1110             "    this.sProvider = sProvider;",
1111             "  }",
1112             "",
1113             "  @Override public InjectConstructor get() {",
1114             "    return newInstance(sProvider.get());",
1115             "  }",
1116             "",
1117             "  public static InjectConstructor_Factory create(Provider<String> sProvider) {",
1118             "    return new InjectConstructor_Factory(sProvider);",
1119             "  }",
1120             "",
1121             "  public static InjectConstructor newInstance(String s) {",
1122             "    return new InjectConstructor(s);",
1123             "  }",
1124             "}");
1125     assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor())
1126         .compilesWithoutError()
1127         .and().generatesSources(expected);
1128   }
1129 
injectConstructorAndMembersInjection()1130   @Test public void injectConstructorAndMembersInjection() {
1131     JavaFileObject file = JavaFileObjects.forSourceLines("test.AllInjections",
1132         "package test;",
1133         "",
1134         "import javax.inject.Inject;",
1135         "",
1136         "class AllInjections {",
1137         "  @Inject String s;",
1138         "  @Inject AllInjections(String s) {}",
1139         "  @Inject void s(String s) {}",
1140         "}");
1141     JavaFileObject expectedFactory =
1142         JavaFileObjects.forSourceLines(
1143             "test.AllInjections_Factory",
1144             "package test;",
1145             "",
1146             GeneratedLines.generatedImports(
1147                 "import dagger.internal.Factory;",
1148                 "import dagger.internal.QualifierMetadata;",
1149                 "import dagger.internal.ScopeMetadata;",
1150                 "import javax.inject.Provider;"),
1151             "",
1152             "@ScopeMetadata",
1153             "@QualifierMetadata",
1154             GeneratedLines.generatedAnnotations(),
1155             "public final class AllInjections_Factory implements Factory<AllInjections> {",
1156             "  private final Provider<String> sProvider;",
1157             "  private final Provider<String> sProvider2;",
1158             "  private final Provider<String> sProvider3;",
1159             "",
1160             "  public AllInjections_Factory(",
1161             "      Provider<String> sProvider,",
1162             "      Provider<String> sProvider2,",
1163             "      Provider<String> sProvider3) {",
1164             "    this.sProvider = sProvider;",
1165             "    this.sProvider2 = sProvider2;",
1166             "    this.sProvider3 = sProvider3;",
1167             "  }",
1168             "",
1169             "  @Override",
1170             "  public AllInjections get() {",
1171             "    AllInjections instance = newInstance(sProvider.get());",
1172             "    AllInjections_MembersInjector.injectS(instance, sProvider2.get());",
1173             "    AllInjections_MembersInjector.injectS2(instance, sProvider3.get());",
1174             "    return instance;",
1175             "  }",
1176             "",
1177             "  public static AllInjections_Factory create(",
1178             "      Provider<String> sProvider,",
1179             "      Provider<String> sProvider2,",
1180             "      Provider<String> sProvider3) {",
1181             "    return new AllInjections_Factory(sProvider, sProvider2, sProvider3);",
1182             "  }",
1183             "",
1184             "  public static AllInjections newInstance(String s) {",
1185             "    return new AllInjections(s);",
1186             "  }",
1187             "}");
1188     assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor())
1189         .compilesWithoutError()
1190         .and()
1191         .generatesSources(expectedFactory);
1192   }
1193 
1194   @Test
wildcardDependency()1195   public void wildcardDependency() {
1196     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
1197         "package test;",
1198         "",
1199         "import java.util.List;",
1200         "import javax.inject.Inject;",
1201         "",
1202         "class InjectConstructor {",
1203         "  @Inject InjectConstructor(List<?> objects) {}",
1204         "}");
1205     JavaFileObject expected =
1206         JavaFileObjects.forSourceLines(
1207             "test.InjectConstructor_Factory",
1208             "package test;",
1209             "",
1210             GeneratedLines.generatedImports(
1211                 "import dagger.internal.Factory;",
1212                 "import dagger.internal.QualifierMetadata;",
1213                 "import dagger.internal.ScopeMetadata;",
1214                 "import java.util.List;",
1215                 "import javax.inject.Provider;"),
1216             "",
1217             "@ScopeMetadata",
1218             "@QualifierMetadata",
1219             GeneratedLines.generatedAnnotations(),
1220             "public final class InjectConstructor_Factory ",
1221             "    implements Factory<InjectConstructor> {",
1222             "",
1223             "  private final Provider<List<?>> objectsProvider;",
1224             "",
1225             "  public InjectConstructor_Factory(Provider<List<?>> objectsProvider) {",
1226             "    this.objectsProvider = objectsProvider;",
1227             "  }",
1228             "",
1229             "  @Override public InjectConstructor get() {",
1230             "    return newInstance(objectsProvider.get());",
1231             "  }",
1232             "",
1233             "  public static InjectConstructor_Factory create(",
1234             "      Provider<List<?>> objectsProvider) {",
1235             "    return new InjectConstructor_Factory(objectsProvider);",
1236             "  }",
1237             "",
1238             "  public static InjectConstructor newInstance(List<?> objects) {",
1239             "    return new InjectConstructor(objects);",
1240             "  }",
1241             "}");
1242     assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor())
1243         .compilesWithoutError()
1244         .and().generatesSources(expected);
1245   }
1246 
1247   @Test
basicNameCollision()1248   public void basicNameCollision() {
1249     JavaFileObject factoryFile = JavaFileObjects.forSourceLines("other.pkg.Factory",
1250         "package other.pkg;",
1251         "",
1252         "public class Factory {}");
1253     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
1254         "package test;",
1255         "",
1256         "import javax.inject.Inject;",
1257         "import other.pkg.Factory;",
1258         "",
1259         "class InjectConstructor {",
1260         "  @Inject InjectConstructor(Factory factory) {}",
1261         "}");
1262     JavaFileObject expected =
1263         JavaFileObjects.forSourceLines(
1264             "test.InjectConstructor_Factory",
1265             "package test;",
1266             "",
1267             GeneratedLines.generatedImports(
1268                 "import dagger.internal.Factory;",
1269                 "import dagger.internal.QualifierMetadata;",
1270                 "import dagger.internal.ScopeMetadata;",
1271                 "import javax.inject.Provider;"),
1272             "",
1273             "@ScopeMetadata",
1274             "@QualifierMetadata",
1275             GeneratedLines.generatedAnnotations(),
1276             "public final class InjectConstructor_Factory ",
1277             "    implements Factory<InjectConstructor> {",
1278             "",
1279             "  private final Provider<other.pkg.Factory> factoryProvider;",
1280             "",
1281             "  public InjectConstructor_Factory(Provider<other.pkg.Factory> factoryProvider) {",
1282             "    this.factoryProvider = factoryProvider;",
1283             "  }",
1284             "",
1285             "  @Override public InjectConstructor get() {",
1286             "    return newInstance(factoryProvider.get());",
1287             "  }",
1288             "",
1289             "  public static InjectConstructor_Factory create(",
1290             "      Provider<other.pkg.Factory> factoryProvider) {",
1291             "    return new InjectConstructor_Factory(factoryProvider);",
1292             "  }",
1293             "",
1294             "  public static InjectConstructor newInstance(",
1295             "      other.pkg.Factory factory) {",
1296             "    return new InjectConstructor(factory);",
1297             "  }",
1298             "}");
1299     assertAbout(javaSources()).that(ImmutableList.of(factoryFile, file))
1300         .processedWith(new ComponentProcessor())
1301         .compilesWithoutError()
1302         .and().generatesSources(expected);
1303   }
1304 
1305   @Test
nestedNameCollision()1306   public void nestedNameCollision() {
1307     JavaFileObject factoryFile = JavaFileObjects.forSourceLines("other.pkg.Outer",
1308         "package other.pkg;",
1309         "",
1310         "public class Outer {",
1311         "  public class Factory {}",
1312         "}");
1313     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
1314         "package test;",
1315         "",
1316         "import javax.inject.Inject;",
1317         "import other.pkg.Outer;",
1318         "",
1319         "class InjectConstructor {",
1320         "  @Inject InjectConstructor(Outer.Factory factory) {}",
1321         "}");
1322     JavaFileObject expected =
1323         JavaFileObjects.forSourceLines(
1324             "test.InjectConstructor_Factory",
1325             "package test;",
1326             "",
1327             GeneratedLines.generatedImports(
1328                 "import dagger.internal.Factory;",
1329                 "import dagger.internal.QualifierMetadata;",
1330                 "import dagger.internal.ScopeMetadata;",
1331                 "import javax.inject.Provider;",
1332                 "import other.pkg.Outer;"),
1333             "",
1334             "@ScopeMetadata",
1335             "@QualifierMetadata",
1336             GeneratedLines.generatedAnnotations(),
1337             "public final class InjectConstructor_Factory ",
1338             "    implements Factory<InjectConstructor> {",
1339             "",
1340             "  private final Provider<Outer.Factory> factoryProvider;",
1341             "",
1342             "  public InjectConstructor_Factory(Provider<Outer.Factory> factoryProvider) {",
1343             "    this.factoryProvider = factoryProvider;",
1344             "  }",
1345             "",
1346             "  @Override public InjectConstructor get() {",
1347             "    return newInstance(factoryProvider.get());",
1348             "  }",
1349             "",
1350             "  public static InjectConstructor_Factory create(",
1351             "      Provider<Outer.Factory> factoryProvider) {",
1352             "    return new InjectConstructor_Factory(factoryProvider);",
1353             "  }",
1354             "",
1355             "  public static InjectConstructor newInstance(",
1356             "      Outer.Factory factory) {",
1357             "    return new InjectConstructor(factory);",
1358             "  }",
1359             "}");
1360     assertAbout(javaSources()).that(ImmutableList.of(factoryFile, file))
1361         .processedWith(new ComponentProcessor())
1362         .compilesWithoutError()
1363         .and().generatesSources(expected);
1364   }
1365 
1366   @Test
samePackageNameCollision()1367   public void samePackageNameCollision() {
1368     JavaFileObject samePackageInterface = JavaFileObjects.forSourceLines("test.CommonName",
1369         "package test;",
1370         "",
1371         "public interface CommonName {}");
1372     JavaFileObject differentPackageInterface = JavaFileObjects.forSourceLines(
1373         "other.pkg.CommonName",
1374         "package other.pkg;",
1375         "",
1376         "public interface CommonName {}");
1377     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
1378         "package test;",
1379         "",
1380         "import javax.inject.Inject;",
1381         "",
1382         "class InjectConstructor implements CommonName {",
1383         "  @Inject InjectConstructor(other.pkg.CommonName otherPackage, CommonName samePackage) {}",
1384         "}");
1385     JavaFileObject expected =
1386         JavaFileObjects.forSourceLines(
1387             "test.InjectConstructor_Factory",
1388             "package test;",
1389             "",
1390             GeneratedLines.generatedImports(
1391                 "import dagger.internal.Factory;",
1392                 "import dagger.internal.QualifierMetadata;",
1393                 "import dagger.internal.ScopeMetadata;",
1394                 "import javax.inject.Provider;"),
1395             "",
1396             "@ScopeMetadata",
1397             "@QualifierMetadata",
1398             GeneratedLines.generatedAnnotations(),
1399             "public final class InjectConstructor_Factory ",
1400             "    implements Factory<InjectConstructor> {",
1401             "",
1402             "  private final Provider<other.pkg.CommonName> otherPackageProvider;",
1403             "  private final Provider<CommonName> samePackageProvider;",
1404             "",
1405             "  public InjectConstructor_Factory(",
1406             "      Provider<other.pkg.CommonName> otherPackageProvider,",
1407             "      Provider<CommonName> samePackageProvider) {",
1408             "    this.otherPackageProvider = otherPackageProvider;",
1409             "    this.samePackageProvider = samePackageProvider;",
1410             "  }",
1411             "",
1412             "  @Override public InjectConstructor get() {",
1413             "    return newInstance(otherPackageProvider.get(), samePackageProvider.get());",
1414             "  }",
1415             "",
1416             "  public static InjectConstructor_Factory create(",
1417             "      Provider<other.pkg.CommonName> otherPackageProvider,",
1418             "      Provider<CommonName> samePackageProvider) {",
1419             "    return new InjectConstructor_Factory(otherPackageProvider, samePackageProvider);",
1420             "  }",
1421             "",
1422             "  public static InjectConstructor newInstance(",
1423             "      other.pkg.CommonName otherPackage, CommonName samePackage) {",
1424             "    return new InjectConstructor(otherPackage, samePackage);",
1425             "  }",
1426             "}");
1427     assertAbout(javaSources())
1428         .that(ImmutableList.of(samePackageInterface, differentPackageInterface, file))
1429         .processedWith(new ComponentProcessor())
1430         .compilesWithoutError()
1431         .and().generatesSources(expected);
1432   }
1433 
1434   @Test
noDeps()1435   public void noDeps() {
1436     JavaFileObject simpleType = JavaFileObjects.forSourceLines("test.SimpleType",
1437         "package test;",
1438         "",
1439         "import javax.inject.Inject;",
1440         "",
1441         "final class SimpleType {",
1442         "  @Inject SimpleType() {}",
1443         "}");
1444     JavaFileObject factory =
1445         JavaFileObjects.forSourceLines(
1446             "test.SimpleType_Factory",
1447             "package test;",
1448             "",
1449             GeneratedLines.generatedImports(
1450                 "import dagger.internal.Factory;",
1451                 "import dagger.internal.QualifierMetadata;",
1452                 "import dagger.internal.ScopeMetadata;"),
1453             "",
1454             "@ScopeMetadata",
1455             "@QualifierMetadata",
1456             GeneratedLines.generatedAnnotations(),
1457             "public final class SimpleType_Factory implements Factory<SimpleType> {",
1458             "  @Override public SimpleType get() {",
1459             "    return newInstance();",
1460             "  }",
1461             "",
1462             "  public static SimpleType_Factory create() {",
1463             "    return InstanceHolder.INSTANCE;",
1464             "  }",
1465             "",
1466             "  public static SimpleType newInstance() {",
1467             "    return new SimpleType();",
1468             "  }",
1469             "",
1470             "  private static final class InstanceHolder {",
1471             "    private static final SimpleType_Factory INSTANCE = new SimpleType_Factory();",
1472             "  }",
1473             "}");
1474     assertAbout(javaSource())
1475         .that(simpleType)
1476         .processedWith(new ComponentProcessor())
1477         .compilesWithoutError()
1478         .and().generatesSources(factory);
1479   }
1480 
simpleComponentWithNesting()1481   @Test public void simpleComponentWithNesting() {
1482     JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines("test.OuterType",
1483         "package test;",
1484         "",
1485         "import dagger.Component;",
1486         "import javax.inject.Inject;",
1487         "",
1488         "final class OuterType {",
1489         "  static class A {",
1490         "    @Inject A() {}",
1491         "  }",
1492         "  static class B {",
1493         "    @Inject A a;",
1494         "  }",
1495         "}");
1496     JavaFileObject aFactory =
1497         JavaFileObjects.forSourceLines(
1498             "test.OuterType_A_Factory",
1499             "package test;",
1500             "",
1501             GeneratedLines.generatedImports(
1502                 "import dagger.internal.Factory;",
1503                 "import dagger.internal.QualifierMetadata;",
1504                 "import dagger.internal.ScopeMetadata;"),
1505             "",
1506             "@ScopeMetadata",
1507             "@QualifierMetadata",
1508             GeneratedLines.generatedAnnotations(),
1509             "public final class OuterType_A_Factory implements Factory<OuterType.A> {",
1510             "  @Override public OuterType.A get() {",
1511             "    return newInstance();",
1512             "  }",
1513             "",
1514             "  public static OuterType_A_Factory create() {",
1515             "    return InstanceHolder.INSTANCE;",
1516             "  }",
1517             "",
1518             "  public static OuterType.A newInstance() {",
1519             "    return new OuterType.A();",
1520             "  }",
1521             "",
1522             "  private static final class InstanceHolder {",
1523             "    private static final OuterType_A_Factory INSTANCE = new OuterType_A_Factory();",
1524             "  }",
1525             "}");
1526     assertAbout(javaSources()).that(ImmutableList.of(nestedTypesFile))
1527         .processedWith(new ComponentProcessor())
1528         .compilesWithoutError()
1529         .and().generatesSources(aFactory);
1530   }
1531 
1532   @Test
testScopedMetadata()1533   public void testScopedMetadata() {
1534     JavaFileObject scopedBinding =
1535         JavaFileObjects.forSourceLines(
1536             "test.ScopedBinding",
1537             "package test;",
1538             "",
1539             "import javax.inject.Inject;",
1540             "import javax.inject.Singleton;",
1541             "",
1542             "@Singleton",
1543             "class ScopedBinding {",
1544             "  @Inject",
1545             "  ScopedBinding() {}",
1546             "}");
1547     Compilation compilation = daggerCompiler().compile(scopedBinding);
1548     assertThat(compilation).succeeded();
1549     assertThat(compilation)
1550         .generatedSourceFile("test.ScopedBinding_Factory")
1551         .containsElementsIn(
1552             JavaFileObjects.forSourceLines(
1553                 "test.ScopedBinding_Factory",
1554                 "package test;",
1555                 "",
1556                 "@ScopeMetadata(\"javax.inject.Singleton\")",
1557                 "@QualifierMetadata",
1558                 GeneratedLines.generatedAnnotations(),
1559                 "public final class ScopedBinding_Factory implements Factory<ScopedBinding> {}"));
1560   }
1561 
1562   @Test
testScopedMetadataWithCustomScope()1563   public void testScopedMetadataWithCustomScope() {
1564     JavaFileObject customScope =
1565         JavaFileObjects.forSourceLines(
1566             "test.CustomScope",
1567             "package test;",
1568             "",
1569             "import javax.inject.Scope;",
1570             "",
1571             "@Scope",
1572             "@interface CustomScope {",
1573             "  String value();",
1574             "}");
1575 
1576     JavaFileObject customAnnotation =
1577         JavaFileObjects.forSourceLines(
1578             "test.CustomAnnotation",
1579             "package test;",
1580             "",
1581             "@interface CustomAnnotation {",
1582             "  String value();",
1583             "}");
1584 
1585     JavaFileObject scopedBinding =
1586         JavaFileObjects.forSourceLines(
1587             "test.ScopedBinding",
1588             "package test;",
1589             "",
1590             "import javax.inject.Inject;",
1591             "import javax.inject.Singleton;",
1592             "",
1593             "@CustomAnnotation(\"someValue\")",
1594             "@CustomScope(\"someOtherValue\")",
1595             "class ScopedBinding {",
1596             "  @Inject",
1597             "  ScopedBinding() {}",
1598             "}");
1599     Compilation compilation =
1600         daggerCompiler().compile(scopedBinding, customScope, customAnnotation);
1601     assertThat(compilation).succeeded();
1602     assertThat(compilation)
1603         .generatedSourceFile("test.ScopedBinding_Factory")
1604         .containsElementsIn(
1605             JavaFileObjects.forSourceLines(
1606                 "test.ScopedBinding_Factory",
1607                 "package test;",
1608                 "",
1609                 "@ScopeMetadata(\"test.CustomScope\")",
1610                 "@QualifierMetadata",
1611                 GeneratedLines.generatedAnnotations(),
1612                 "public final class ScopedBinding_Factory implements Factory<ScopedBinding> {}"));
1613   }
1614 
1615   @Test
testQualifierMetadata()1616   public void testQualifierMetadata() {
1617     JavaFileObject someBinding =
1618         JavaFileObjects.forSourceLines(
1619             "test.SomeBinding",
1620             "package test;",
1621             "",
1622             "import javax.inject.Inject;",
1623             "import javax.inject.Singleton;",
1624             "",
1625             "@NonQualifier",
1626             "@MisplacedQualifier",
1627             "class SomeBinding {",
1628             "  @NonQualifier @FieldQualifier @Inject String injectField;",
1629             "  @NonQualifier @MisplacedQualifier String nonDaggerField;",
1630             "",
1631             "  @NonQualifier",
1632             "  @Inject",
1633             "  SomeBinding(@NonQualifier @ConstructorParameterQualifier Double d) {}",
1634             "",
1635             "  @NonQualifier",
1636             "  @MisplacedQualifier",
1637             "  SomeBinding(@NonQualifier @MisplacedQualifier Double d, int i) {}",
1638             "",
1639             "  @NonQualifier",
1640             "  @MisplacedQualifier",
1641             "  @Inject",
1642             "  void injectMethod(@NonQualifier @MethodParameterQualifier Float f) {}",
1643             "",
1644             "  @NonQualifier",
1645             "  @MisplacedQualifier",
1646             "  void nonDaggerMethod(@NonQualifier @MisplacedQualifier Float f) {}",
1647             "}");
1648     JavaFileObject fieldQualifier =
1649         JavaFileObjects.forSourceLines(
1650             "test.FieldQualifier",
1651             "package test;",
1652             "",
1653             "import javax.inject.Qualifier;",
1654             "",
1655             "@Qualifier",
1656             "@interface FieldQualifier {}");
1657     JavaFileObject constructorParameterQualifier =
1658         JavaFileObjects.forSourceLines(
1659             "test.ConstructorParameterQualifier",
1660             "package test;",
1661             "",
1662             "import javax.inject.Qualifier;",
1663             "",
1664             "@Qualifier",
1665             "@interface ConstructorParameterQualifier {}");
1666     JavaFileObject methodParameterQualifier =
1667         JavaFileObjects.forSourceLines(
1668             "test.MethodParameterQualifier",
1669             "package test;",
1670             "",
1671             "import javax.inject.Qualifier;",
1672             "",
1673             "@Qualifier",
1674             "@interface MethodParameterQualifier {}");
1675     JavaFileObject misplacedQualifier =
1676         JavaFileObjects.forSourceLines(
1677             "test.MisplacedQualifier",
1678             "package test;",
1679             "",
1680             "import javax.inject.Qualifier;",
1681             "",
1682             "@Qualifier",
1683             "@interface MisplacedQualifier {}");
1684     JavaFileObject nonQualifier =
1685         JavaFileObjects.forSourceLines(
1686             "test.NonQualifier",
1687             "package test;",
1688             "",
1689             "@interface NonQualifier {}");
1690     Compilation compilation =
1691         daggerCompiler().compile(
1692             someBinding,
1693             fieldQualifier,
1694             constructorParameterQualifier,
1695             methodParameterQualifier,
1696             misplacedQualifier,
1697             nonQualifier);
1698     assertThat(compilation).succeeded();
1699     assertThat(compilation)
1700         .generatedSourceFile("test.SomeBinding_Factory")
1701         .containsElementsIn(
1702             JavaFileObjects.forSourceLines(
1703                 "test.SomeBinding_Factory",
1704                 "package test;",
1705                 "",
1706                 // Verifies that the @QualifierMetadata for the generated Factory does not contain
1707                 // @MisplacedQualifier, @NonQualifier, @MethodParameterQualifier or @FieldQualifier.
1708                 "@ScopeMetadata",
1709                 "@QualifierMetadata(\"test.ConstructorParameterQualifier\")",
1710                 GeneratedLines.generatedAnnotations(),
1711                 "public final class SomeBinding_Factory implements Factory<SomeBinding> {}"));
1712     assertThat(compilation)
1713         .generatedSourceFile("test.SomeBinding_MembersInjector")
1714         .containsElementsIn(
1715             JavaFileObjects.forSourceLines(
1716                 "test.SomeBinding_MembersInjector",
1717                 "package test;",
1718                 "",
1719                 // Verifies that the @QualifierMetadata for the generated MembersInjector does not
1720                 // contain @MisplacedQualifier, @NonQualifier, or @ConstructorParameterQualifier.
1721                 "@QualifierMetadata({",
1722                 "    \"test.FieldQualifier\",",
1723                 "    \"test.MethodParameterQualifier\"",
1724                 "})",
1725                 GeneratedLines.generatedAnnotations(),
1726                 "public final class SomeBinding_MembersInjector",
1727                 "    implements MembersInjector<SomeBinding> {}"));
1728   }
1729 
1730   @Test
testComplexQualifierMetadata()1731   public void testComplexQualifierMetadata() {
1732     JavaFileObject someBinding =
1733         JavaFileObjects.forSourceLines(
1734             "test.SomeBinding",
1735             "package test;",
1736             "",
1737             "import javax.inject.Inject;",
1738             "import javax.inject.Inject;",
1739             "",
1740             "class SomeBinding {",
1741             "  @QualifierWithValue(1) @Inject String injectField;",
1742             "",
1743             "  @Inject",
1744             "  SomeBinding(",
1745             "      @pkg1.SameNameQualifier String str1,",
1746             "      @pkg2.SameNameQualifier String str2) {}",
1747             "",
1748             "  @Inject",
1749             "  void injectMethod(@test.Outer.NestedQualifier Float f) {}",
1750             "}");
1751     JavaFileObject qualifierWithValue =
1752         JavaFileObjects.forSourceLines(
1753             "test.QualifierWithValue",
1754             "package test;",
1755             "",
1756             "import javax.inject.Qualifier;",
1757             "",
1758             "@Qualifier",
1759             "@interface QualifierWithValue {",
1760             "  int value();",
1761             "}");
1762     JavaFileObject pkg1SameNameQualifier =
1763         JavaFileObjects.forSourceLines(
1764             "pkg1.SameNameQualifier",
1765             "package pkg1;",
1766             "",
1767             "import javax.inject.Qualifier;",
1768             "",
1769             "@Qualifier",
1770             "public @interface SameNameQualifier {}");
1771     JavaFileObject pkg2SameNameQualifier =
1772         JavaFileObjects.forSourceLines(
1773             "pkg2.SameNameQualifier",
1774             "package pkg2;",
1775             "",
1776             "import javax.inject.Qualifier;",
1777             "",
1778             "@Qualifier",
1779             "public @interface SameNameQualifier {}");
1780     JavaFileObject nestedQualifier =
1781         JavaFileObjects.forSourceLines(
1782             "test.Outer",
1783             "package test;",
1784             "",
1785             "import javax.inject.Qualifier;",
1786             "",
1787             "interface Outer {",
1788             "  @Qualifier",
1789             "  @interface NestedQualifier {}",
1790             "}");
1791     Compilation compilation =
1792         daggerCompiler().compile(
1793             someBinding,
1794             qualifierWithValue,
1795             pkg1SameNameQualifier,
1796             pkg2SameNameQualifier,
1797             nestedQualifier);
1798     assertThat(compilation).succeeded();
1799     assertThat(compilation)
1800         .generatedSourceFile("test.SomeBinding_Factory")
1801         .containsElementsIn(
1802             JavaFileObjects.forSourceLines(
1803                 "test.SomeBinding_Factory",
1804                 "package test;",
1805                 "",
1806                 "@ScopeMetadata",
1807                 "@QualifierMetadata({\"pkg1.SameNameQualifier\", \"pkg2.SameNameQualifier\"})",
1808                 GeneratedLines.generatedAnnotations(),
1809                 "public final class SomeBinding_Factory implements Factory<SomeBinding> {}"));
1810     assertThat(compilation)
1811         .generatedSourceFile("test.SomeBinding_MembersInjector")
1812         .containsElementsIn(
1813             JavaFileObjects.forSourceLines(
1814                 "test.SomeBinding_MembersInjector",
1815                 "package test;",
1816                 "",
1817                 "@QualifierMetadata({",
1818                 "    \"test.QualifierWithValue\",",
1819                 "    \"test.Outer.NestedQualifier\"",
1820                 "})",
1821                 GeneratedLines.generatedAnnotations(),
1822                 "public final class SomeBinding_MembersInjector",
1823                 "    implements MembersInjector<SomeBinding> {}"));
1824   }
1825 
1826   @Test
testBaseClassQualifierMetadata()1827   public void testBaseClassQualifierMetadata() {
1828     JavaFileObject foo =
1829         JavaFileObjects.forSourceLines(
1830             "test.Foo",
1831             "package test;",
1832             "",
1833             "import javax.inject.Inject;",
1834             "import javax.inject.Singleton;",
1835             "",
1836             "class Foo extends FooBase {",
1837             "  @FooFieldQualifier @Inject String injectField;",
1838             "",
1839             "  @Inject",
1840             "  Foo(@FooConstructorQualifier int i) { super(i); }",
1841             "",
1842             "  @Inject",
1843             "  void injectMethod(@FooMethodQualifier float f) {}",
1844             "}");
1845     JavaFileObject fooFieldQualifier =
1846         JavaFileObjects.forSourceLines(
1847             "test.FooFieldQualifier",
1848             "package test;",
1849             "",
1850             "import javax.inject.Qualifier;",
1851             "",
1852             "@Qualifier",
1853             "@interface FooFieldQualifier {}");
1854     JavaFileObject fooConstructorQualifier =
1855         JavaFileObjects.forSourceLines(
1856             "test.FooConstructorQualifier",
1857             "package test;",
1858             "",
1859             "import javax.inject.Qualifier;",
1860             "",
1861             "@Qualifier",
1862             "@interface FooConstructorQualifier {}");
1863     JavaFileObject fooMethodQualifier =
1864         JavaFileObjects.forSourceLines(
1865             "test.FooMethodQualifier",
1866             "package test;",
1867             "",
1868             "import javax.inject.Qualifier;",
1869             "",
1870             "@Qualifier",
1871             "@interface FooMethodQualifier {}");
1872     JavaFileObject fooBase =
1873         JavaFileObjects.forSourceLines(
1874             "test.FooBase",
1875             "package test;",
1876             "",
1877             "import javax.inject.Inject;",
1878             "import javax.inject.Singleton;",
1879             "",
1880             "class FooBase {",
1881             "  @FooBaseFieldQualifier @Inject String injectField;",
1882             "",
1883             "  @Inject",
1884             "  FooBase(@FooBaseConstructorQualifier int i) {}",
1885             "",
1886             "  @Inject",
1887             "  void injectMethod(@FooBaseMethodQualifier float f) {}",
1888             "}");
1889     JavaFileObject fooBaseFieldQualifier =
1890         JavaFileObjects.forSourceLines(
1891             "test.FooBaseFieldQualifier",
1892             "package test;",
1893             "",
1894             "import javax.inject.Qualifier;",
1895             "",
1896             "@Qualifier",
1897             "@interface FooBaseFieldQualifier {}");
1898     JavaFileObject fooBaseConstructorQualifier =
1899         JavaFileObjects.forSourceLines(
1900             "test.FooBaseConstructorQualifier",
1901             "package test;",
1902             "",
1903             "import javax.inject.Qualifier;",
1904             "",
1905             "@Qualifier",
1906             "@interface FooBaseConstructorQualifier {}");
1907     JavaFileObject fooBaseMethodQualifier =
1908         JavaFileObjects.forSourceLines(
1909             "test.FooBaseMethodQualifier",
1910             "package test;",
1911             "",
1912             "import javax.inject.Qualifier;",
1913             "",
1914             "@Qualifier",
1915             "@interface FooBaseMethodQualifier {}");
1916     Compilation compilation =
1917         daggerCompiler().compile(
1918             foo,
1919             fooBase,
1920             fooFieldQualifier,
1921             fooConstructorQualifier,
1922             fooMethodQualifier,
1923             fooBaseFieldQualifier,
1924             fooBaseConstructorQualifier,
1925             fooBaseMethodQualifier);
1926     assertThat(compilation).succeeded();
1927     assertThat(compilation)
1928         .generatedSourceFile("test.Foo_Factory")
1929         .containsElementsIn(
1930             JavaFileObjects.forSourceLines(
1931                 "test.Foo_Factory",
1932                 "package test;",
1933                 "",
1934                 "@ScopeMetadata",
1935                 // Verifies that Foo_Factory only contains Foo's qualifiers and not FooBase's too.
1936                 "@QualifierMetadata(\"test.FooConstructorQualifier\")",
1937                 GeneratedLines.generatedAnnotations(),
1938                 "public final class Foo_Factory implements Factory<Foo> {}"));
1939     assertThat(compilation)
1940         .generatedSourceFile("test.Foo_MembersInjector")
1941         .containsElementsIn(
1942             JavaFileObjects.forSourceLines(
1943                 "test.Foo_MembersInjector",
1944                 "package test;",
1945                 "",
1946                 // Verifies that Foo_Factory only contains Foo's qualifiers and not FooBase's too.
1947                 "@QualifierMetadata({",
1948                 "    \"test.FooFieldQualifier\",",
1949                 "    \"test.FooMethodQualifier\"",
1950                 "})",
1951                 GeneratedLines.generatedAnnotations(),
1952                 "public final class Foo_MembersInjector implements MembersInjector<Foo> {}"));
1953     assertThat(compilation)
1954         .generatedSourceFile("test.FooBase_Factory")
1955         .containsElementsIn(
1956             JavaFileObjects.forSourceLines(
1957                 "test.Foo_Factory",
1958                 "package test;",
1959                 "",
1960                 "@ScopeMetadata",
1961                 "@QualifierMetadata(\"test.FooBaseConstructorQualifier\")",
1962                 GeneratedLines.generatedAnnotations(),
1963                 "public final class FooBase_Factory implements Factory<FooBase> {}"));
1964     assertThat(compilation)
1965         .generatedSourceFile("test.FooBase_MembersInjector")
1966         .containsElementsIn(
1967             JavaFileObjects.forSourceLines(
1968                 "test.FooBase_MembersInjector",
1969                 "package test;",
1970                 "",
1971                 "@QualifierMetadata({",
1972                 "    \"test.FooBaseFieldQualifier\",",
1973                 "    \"test.FooBaseMethodQualifier\"",
1974                 "})",
1975                 GeneratedLines.generatedAnnotations(),
1976                 "public final class FooBase_MembersInjector",
1977                 "    implements MembersInjector<FooBase> {}"));
1978   }
1979 }
1980