• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.internal.codegen;
18 
19 import androidx.room.compiler.processing.util.Source;
20 import com.google.common.collect.ImmutableCollection;
21 import dagger.testing.compile.CompilerTests;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
25 import org.junit.runners.Parameterized.Parameters;
26 
27 @RunWith(Parameterized.class)
28 public class AssistedFactoryErrorsTest {
29   @Parameters(name = "{0}")
parameters()30   public static ImmutableCollection<Object[]> parameters() {
31     return CompilerMode.TEST_PARAMETERS;
32   }
33 
34   private final CompilerMode compilerMode;
35 
AssistedFactoryErrorsTest(CompilerMode compilerMode)36   public AssistedFactoryErrorsTest(CompilerMode compilerMode) {
37     this.compilerMode = compilerMode;
38   }
39 
40   @Test
testFactoryNotAbstract()41   public void testFactoryNotAbstract() {
42     Source foo =
43         CompilerTests.javaSource(
44             "test.Factory",
45             "package test;",
46             "",
47             "import dagger.assisted.AssistedFactory;",
48             "",
49             "@AssistedFactory class Factory {}");
50 
51     CompilerTests.daggerCompiler(foo)
52         .withProcessingOptions(compilerMode.processorOptions())
53         .compile(
54             subject -> {
55               subject.hasErrorCount(1);
56               subject.hasErrorContaining(
57                   "The @AssistedFactory-annotated type must be either an abstract class or "
58                       + "interface.");
59             });
60   }
61 
62   @Test
testNestedFactoryNotStatic()63   public void testNestedFactoryNotStatic() {
64     Source foo =
65         CompilerTests.javaSource(
66             "test.Foo",
67             "package test;",
68             "",
69             "import dagger.assisted.Assisted;",
70             "import dagger.assisted.AssistedInject;",
71             "import dagger.assisted.AssistedFactory;",
72             "",
73             "class Foo {",
74             "  @AssistedInject",
75             "  Foo(@Assisted int i) {}",
76             "",
77             "  @AssistedFactory",
78             "  abstract class Factory {",
79             "    abstract Foo create(int i);",
80             "  }",
81             "}");
82 
83     CompilerTests.daggerCompiler(foo)
84         .withProcessingOptions(compilerMode.processorOptions())
85         .compile(
86             subject -> {
87               subject.hasErrorCount(1);
88               subject.hasErrorContaining("Nested @AssistedFactory-annotated types must be static.");
89             });
90   }
91 
92   @Test
testFactoryMissingAbstractMethod()93   public void testFactoryMissingAbstractMethod() {
94     Source factory =
95         CompilerTests.javaSource(
96             "test.Factory",
97             "package test;",
98             "",
99             "import dagger.assisted.AssistedFactory;",
100             "",
101             "@AssistedFactory interface Factory {}");
102 
103     CompilerTests.daggerCompiler(factory)
104         .withProcessingOptions(compilerMode.processorOptions())
105         .compile(
106             subject -> {
107               subject.hasErrorCount(1);
108               subject.hasErrorContaining(
109                   "The @AssistedFactory-annotated type is missing an abstract, non-default method "
110                       + "whose return type matches the assisted injection type.");
111             });
112   }
113 
114   @Test
testFactoryReturnsNonDeclaredType()115   public void testFactoryReturnsNonDeclaredType() {
116     Source noInject =
117         CompilerTests.javaSource(
118             "test.NoInject",
119             "package test;",
120             "",
121             "final class NoInject {}");
122 
123     Source noAssistedParam =
124         CompilerTests.javaSource(
125             "test.NoAssistedParam",
126             "package test;",
127             "",
128             "import dagger.assisted.AssistedInject;",
129             "",
130             "final class NoAssistedParam {",
131             "  @AssistedInject NoAssistedParam() {}",
132             "}");
133 
134     Source factory =
135         CompilerTests.javaSource(
136             "test.Factory",
137             "package test;",
138             "",
139             "import dagger.assisted.AssistedFactory;",
140             "",
141             "@AssistedFactory",
142             "interface Factory<T> {",
143             "  int createInt();", // Fails return type not @AssistedInject
144             "",
145             "  NoInject createNoInject();", // Fails return type not @AssistedInject
146             "",
147             "  NoAssistedParam createNoAssistedParam();", // Succeeds
148             "",
149             "  T createT();", // Fails return type not @AssistedInject
150             "}");
151 
152     CompilerTests.daggerCompiler(factory, noInject, noAssistedParam)
153         .withProcessingOptions(compilerMode.processorOptions())
154         .compile(
155             subject -> {
156               subject.hasErrorCount(4);
157               subject.hasErrorContaining(
158                       "The @AssistedFactory-annotated type should contain a single abstract, "
159                           + "non-default method but found multiple: ["
160                           + "test.Factory.createInt(), "
161                           + "test.Factory.createNoInject(), "
162                           + "test.Factory.createNoAssistedParam(), "
163                           + "test.Factory.createT()"
164                           + "]")
165                   .onSource(factory)
166                   .onLine(6);
167               subject.hasErrorContaining(
168                       "Invalid return type: int. "
169                           + "An assisted factory's abstract method must return a type with an "
170                           + "@AssistedInject-annotated constructor.")
171                   .onSource(factory)
172                   .onLine(7);
173               subject.hasErrorContaining(
174                       "Invalid return type: test.NoInject. "
175                           + "An assisted factory's abstract method must return a type with an "
176                           + "@AssistedInject-annotated constructor.")
177                   .onSource(factory)
178                   .onLine(9);
179               subject.hasErrorContaining(
180                       "Invalid return type: T. "
181                           + "An assisted factory's abstract method must return a type with an "
182                           + "@AssistedInject-annotated constructor.")
183                   .onSource(factory)
184                   .onLine(13);
185             });
186   }
187 
188   @Test
testFactoryMultipleAbstractMethods()189   public void testFactoryMultipleAbstractMethods() {
190     Source foo =
191         CompilerTests.javaSource(
192             "test.Foo",
193             "package test;",
194             "",
195             "import dagger.assisted.Assisted;",
196             "import dagger.assisted.AssistedInject;",
197             "",
198             "class Foo {",
199             "  @AssistedInject Foo(@Assisted int i) {}",
200             "}");
201 
202     Source fooFactoryInterface =
203         CompilerTests.javaSource(
204             "test.FooFactoryInterface",
205             "package test;",
206             "",
207             "interface FooFactoryInterface {",
208             " Foo createFoo1(int i);",
209             "}");
210 
211     Source fooFactory =
212         CompilerTests.javaSource(
213             "test.FooFactory",
214             "package test;",
215             "",
216             "import dagger.assisted.AssistedFactory;",
217             "",
218             "@AssistedFactory",
219             "interface FooFactory extends FooFactoryInterface {",
220             " Foo createFoo2(int i);",
221             "",
222             " Foo createFoo3(int i);",
223             "}");
224 
225     CompilerTests.daggerCompiler(foo, fooFactory, fooFactoryInterface)
226         .withProcessingOptions(compilerMode.processorOptions())
227         .compile(
228             subject -> {
229               subject.hasErrorCount(1);
230               subject.hasErrorContaining(
231                       "The @AssistedFactory-annotated type should contain a single abstract, "
232                           + "non-default method but found multiple: ["
233                           + "test.FooFactoryInterface.createFoo1(int), "
234                           + "test.FooFactory.createFoo2(int), "
235                           + "test.FooFactory.createFoo3(int)"
236                           + "]");
237             });
238   }
239 
240   @Test
testFactoryMismatchingParameter()241   public void testFactoryMismatchingParameter() {
242     Source foo =
243         CompilerTests.javaSource(
244             "test.Foo",
245             "package test;",
246             "",
247             "import dagger.assisted.Assisted;",
248             "import dagger.assisted.AssistedInject;",
249             "",
250             "class Foo {",
251             "  @AssistedInject Foo(@Assisted int i) {}",
252             "}");
253 
254     Source fooFactory =
255         CompilerTests.javaSource(
256             "test.FooFactory",
257             "package test;",
258             "",
259             "import dagger.assisted.AssistedFactory;",
260             "",
261             "@AssistedFactory",
262             "interface FooFactory {",
263             " Foo create(String i);",
264             "}");
265 
266     CompilerTests.daggerCompiler(foo, fooFactory)
267         .withProcessingOptions(compilerMode.processorOptions())
268         .compile(
269             subject -> {
270               subject.hasErrorCount(1);
271               subject.hasErrorContaining(
272                   "The parameters in the factory method must match the @Assisted parameters in "
273                       + "test.Foo.");
274               subject.hasErrorContaining("  Actual: test.FooFactory#create(java.lang.String)");
275               subject.hasErrorContaining("Expected: test.FooFactory#create(int)");
276             });
277   }
278 
279   @Test
testFactoryMismatchingGenericParameter()280   public void testFactoryMismatchingGenericParameter() {
281     Source foo =
282         CompilerTests.javaSource(
283             "test.Foo",
284             "package test;",
285             "",
286             "import dagger.assisted.Assisted;",
287             "import dagger.assisted.AssistedInject;",
288             "",
289             "class Foo<T> {",
290             "  @AssistedInject Foo(@Assisted T t) {}",
291             "}");
292 
293     Source fooFactory =
294         CompilerTests.javaSource(
295             "test.FooFactory",
296             "package test;",
297             "",
298             "import dagger.assisted.AssistedFactory;",
299             "",
300             "@AssistedFactory",
301             "interface FooFactory<T> {",
302             "  Foo<T> create(String str);",
303             "}");
304 
305     CompilerTests.daggerCompiler(foo, fooFactory)
306         .withProcessingOptions(compilerMode.processorOptions())
307         .compile(
308             subject -> {
309               subject.hasErrorCount(1);
310               subject.hasErrorContaining(
311                   "The parameters in the factory method must match the @Assisted parameters in "
312                       + "test.Foo<T>.");
313               subject.hasErrorContaining("  Actual: test.FooFactory#create(java.lang.String)");
314               subject.hasErrorContaining("Expected: test.FooFactory#create(T)");
315             });
316   }
317 
318   @Test
testFactoryDuplicateGenericParameter()319   public void testFactoryDuplicateGenericParameter() {
320     Source foo =
321         CompilerTests.javaSource(
322             "test.Foo",
323             "package test;",
324             "",
325             "import dagger.assisted.Assisted;",
326             "import dagger.assisted.AssistedInject;",
327             "",
328             "class Foo<T> {",
329             "  @AssistedInject Foo(@Assisted String str, @Assisted T t) {}",
330             "}");
331 
332     Source fooFactory =
333         CompilerTests.javaSource(
334             "test.FooFactory",
335             "package test;",
336             "",
337             "import dagger.assisted.AssistedFactory;",
338             "",
339             "@AssistedFactory",
340             "interface FooFactory {",
341             "  Foo<String> create(String str1, String str2);",
342             "}");
343 
344     CompilerTests.daggerCompiler(foo, fooFactory)
345         .withProcessingOptions(compilerMode.processorOptions())
346         .compile(
347             subject -> {
348               subject.hasErrorCount(1);
349               subject.hasErrorContaining(
350                   "@AssistedFactory method has duplicate @Assisted types: "
351                       + "@Assisted java.lang.String");
352             });
353   }
354 
355   @Test
testAssistedInjectionRequest()356   public void testAssistedInjectionRequest() {
357     Source foo =
358         CompilerTests.javaSource(
359             "test.Foo",
360             "package test;",
361             "",
362             "import dagger.assisted.Assisted;",
363             "import dagger.assisted.AssistedInject;",
364             "",
365             "class Foo {",
366             "  @AssistedInject Foo(@Assisted String str) {}",
367             "}");
368 
369     Source bar =
370         CompilerTests.javaSource(
371             "test.Bar",
372             "package test;",
373             "",
374             "import javax.inject.Inject;",
375             "import javax.inject.Provider;",
376             "",
377             "class Bar {",
378             "  @Inject",
379             "  Bar(Foo foo, Provider<Foo> fooProvider) {}",
380             "}");
381 
382     Source module =
383         CompilerTests.javaSource(
384             "test.FooModule",
385             "package test;",
386             "",
387             "import dagger.Module;",
388             "import dagger.Provides;",
389             "import javax.inject.Provider;",
390             "",
391             "@Module",
392             "class FooModule {",
393             "  @Provides",
394             "  static int provideInt(Foo foo, Provider<Foo> fooProvider) {",
395             "    return 0;",
396             "  }",
397             "}");
398 
399     Source component =
400         CompilerTests.javaSource(
401             "test.FooComponent",
402             "package test;",
403             "",
404             "import dagger.Component;",
405             "import javax.inject.Provider;",
406             "",
407             "@Component",
408             "interface FooComponent {",
409             "  Foo foo();",
410             "",
411             "  Provider<Foo> fooProvider();",
412             "}");
413 
414     CompilerTests.daggerCompiler(foo, bar, module, component)
415         .withProcessingOptions(compilerMode.processorOptions())
416         .compile(
417             subject -> {
418               subject.hasErrorCount(6);
419 
420               String fooError =
421                   "Dagger does not support injecting @AssistedInject type, test.Foo. "
422                       + "Did you mean to inject its assisted factory type instead?";
423               subject.hasErrorContaining(fooError).onSource(bar).onLine(8);
424               subject.hasErrorContaining(fooError).onSource(module).onLine(10);
425               subject.hasErrorContaining(fooError).onSource(component).onLine(8);
426 
427               String fooProviderError =
428                   "Dagger does not support injecting @AssistedInject type, "
429                       + "javax.inject.Provider<test.Foo>. "
430                       + "Did you mean to inject its assisted factory type instead?";
431               subject.hasErrorContaining(fooProviderError).onSource(bar).onLine(8);
432               subject.hasErrorContaining(fooProviderError).onSource(module).onLine(10);
433               subject.hasErrorContaining(fooProviderError).onSource(component).onLine(10);
434             });
435   }
436 
437   @Test
testProvidesAssistedBindings()438   public void testProvidesAssistedBindings() {
439     Source foo =
440         CompilerTests.javaSource(
441             "test.Foo",
442             "package test;",
443             "",
444             "import dagger.assisted.Assisted;",
445             "import dagger.assisted.AssistedInject;",
446             "import dagger.assisted.AssistedFactory;",
447             "",
448             "class Foo {",
449             "  @AssistedInject Foo(@Assisted int i) {}",
450             "",
451             "  @AssistedFactory",
452             "  interface Factory {",
453             "    Foo create(int i);",
454             "  }",
455             "}");
456 
457     Source module =
458         CompilerTests.javaSource(
459             "test.FooModule",
460             "package test;",
461             "",
462             "import dagger.Module;",
463             "import dagger.Provides;",
464             "import javax.inject.Provider;",
465             "",
466             "@Module",
467             "class FooModule {",
468             "  @Provides",
469             "  static Foo provideFoo() {",
470             "    return null;",
471             "  }",
472             "",
473             "  @Provides",
474             "  static Foo.Factory provideFooFactory() {",
475             "    return null;",
476             "  }",
477             "}");
478 
479     CompilerTests.daggerCompiler(foo, module)
480         .withProcessingOptions(compilerMode.processorOptions())
481         .compile(
482             subject -> {
483               subject.hasErrorCount(2);
484               subject.hasErrorContaining(
485                       "[test.Foo] Dagger does not support providing @AssistedInject types.")
486                   .onSource(module)
487                   .onLine(10);
488               subject.hasErrorContaining(
489                       "[test.Foo.Factory] Dagger does not support providing @AssistedFactory "
490                           + "types.")
491                   .onSource(module)
492                   .onLine(15);
493             });
494   }
495 
496   @Test
testProvidesAssistedBindingsAsFactoryBindsInstance()497   public void testProvidesAssistedBindingsAsFactoryBindsInstance() {
498     Source foo =
499         CompilerTests.javaSource(
500             "test.Foo",
501             "package test;",
502             "",
503             "import dagger.assisted.Assisted;",
504             "import dagger.assisted.AssistedInject;",
505             "import dagger.assisted.AssistedFactory;",
506             "",
507             "class Foo {",
508             "  @AssistedInject Foo(@Assisted int i) {}",
509             "",
510             "  @AssistedFactory",
511             "  interface Factory {",
512             "    Foo create(int i);",
513             "  }",
514             "}");
515 
516     Source component =
517         CompilerTests.javaSource(
518             "test.FooComponent",
519             "package test;",
520             "",
521             "import dagger.Component;",
522             "import dagger.BindsInstance;",
523             "",
524             "@Component",
525             "interface FooComponent {",
526             "  @Component.Factory",
527             "  interface Factory {",
528             "    FooComponent create(",
529             "        @BindsInstance Foo foo,",
530             "        @BindsInstance Foo.Factory fooFactory);",
531             "  }",
532             "}");
533 
534     CompilerTests.daggerCompiler(foo, component)
535         .withProcessingOptions(compilerMode.processorOptions())
536         .compile(
537             subject -> {
538               subject.hasErrorCount(2);
539               subject.hasErrorContaining(
540                       "[test.Foo] Dagger does not support providing @AssistedInject types.")
541                   .onSource(component)
542                   .onLine(11);
543               subject.hasErrorContaining(
544                       "[test.Foo.Factory] Dagger does not support providing @AssistedFactory "
545                           + "types.")
546                   .onSource(component)
547                   .onLine(12);
548             });
549   }
550 
551   @Test
testProvidesAssistedBindingsAsBuilderBindsInstance()552   public void testProvidesAssistedBindingsAsBuilderBindsInstance() {
553     Source foo =
554         CompilerTests.javaSource(
555             "test.Foo",
556             "package test;",
557             "",
558             "import dagger.assisted.Assisted;",
559             "import dagger.assisted.AssistedInject;",
560             "import dagger.assisted.AssistedFactory;",
561             "",
562             "class Foo {",
563             "  @AssistedInject Foo(@Assisted int i) {}",
564             "",
565             "  @AssistedFactory",
566             "  interface Factory {",
567             "    Foo create(int i);",
568             "  }",
569             "}");
570 
571     Source component =
572         CompilerTests.javaSource(
573             "test.FooComponent",
574             "package test;",
575             "",
576             "import dagger.Component;",
577             "import dagger.BindsInstance;",
578             "",
579             "@Component",
580             "interface FooComponent {",
581             "  @Component.Builder",
582             "  interface Builder {",
583             "    @BindsInstance Builder foo(Foo foo);",
584             "    @BindsInstance Builder fooFactory(Foo.Factory fooFactory);",
585             "    FooComponent build();",
586             "  }",
587             "}");
588 
589     CompilerTests.daggerCompiler(foo, component)
590         .withProcessingOptions(compilerMode.processorOptions())
591         .compile(
592             subject -> {
593               subject.hasErrorCount(2);
594               subject.hasErrorContaining(
595                       "[test.Foo] Dagger does not support providing @AssistedInject types.")
596                   .onSource(component)
597                   .onLine(10);
598               subject.hasErrorContaining(
599                       "[test.Foo.Factory] Dagger does not support providing @AssistedFactory "
600                           + "types.")
601                   .onSource(component)
602                   .onLine(11);
603             });
604   }
605 
606   @Test
testProvidesAssistedBindingsAsOptional()607   public void testProvidesAssistedBindingsAsOptional() {
608     Source foo =
609         CompilerTests.javaSource(
610             "test.Foo",
611             "package test;",
612             "",
613             "import dagger.assisted.Assisted;",
614             "import dagger.assisted.AssistedInject;",
615             "import dagger.assisted.AssistedFactory;",
616             "",
617             "class Foo {",
618             "  @AssistedInject Foo() {}",
619             "",
620             "  @AssistedFactory",
621             "  interface Factory {",
622             "    Foo create();",
623             "  }",
624             "}");
625 
626     Source module =
627         CompilerTests.javaSource(
628             "test.FooModule",
629             "package test;",
630             "",
631             "import dagger.BindsOptionalOf;",
632             "import dagger.Module;",
633             "import dagger.Provides;",
634             "",
635             "@Module",
636             "interface FooModule {",
637             "  @BindsOptionalOf Foo optionalFoo();",
638             "",
639             "  @BindsOptionalOf Foo.Factory optionalFooFactory();",
640             "}");
641 
642     CompilerTests.daggerCompiler(foo, module)
643         .withProcessingOptions(compilerMode.processorOptions())
644         .compile(
645             subject -> {
646               subject.hasErrorCount(2);
647               subject.hasErrorContaining(
648                       "[test.Foo] Dagger does not support providing @AssistedInject types.")
649                   .onSource(module)
650                   .onLine(9);
651               subject.hasErrorContaining(
652                       "[test.Foo.Factory] Dagger does not support providing @AssistedFactory "
653                           + "types.")
654                   .onSource(module)
655                   .onLine(11);
656             });
657   }
658 
659   @Test
testInjectsLazyOfAssistedFactory()660   public void testInjectsLazyOfAssistedFactory() {
661     Source foo =
662         CompilerTests.javaSource(
663             "test.Foo",
664             "package test;",
665             "",
666             "import dagger.assisted.Assisted;",
667             "import dagger.assisted.AssistedInject;",
668             "import dagger.assisted.AssistedFactory;",
669             "",
670             "class Foo {",
671             "  @AssistedInject Foo(@Assisted int i) {}",
672             "",
673             "  @AssistedFactory",
674             "  interface Factory {",
675             "    Foo create(int i);",
676             "  }",
677             "}");
678 
679     Source bar =
680         CompilerTests.javaSource(
681             "test.Bar",
682             "package test;",
683             "",
684             "import dagger.Lazy;",
685             "import javax.inject.Inject;",
686             "",
687             "class Bar {",
688             "  @Inject",
689             "  Bar(Foo.Factory fooFactory, Lazy<Foo.Factory> fooFactoryLazy) {}",
690             "}");
691 
692 
693     CompilerTests.daggerCompiler(foo, bar)
694         .withProcessingOptions(compilerMode.processorOptions())
695         .compile(
696             subject -> {
697               subject.hasErrorCount(1);
698               subject.hasErrorContaining(
699                       "Dagger does not support injecting Lazy<T>, Producer<T>, or Produced<T> "
700                           + "when T is an @AssistedFactory-annotated type such as test.Foo.Factory")
701                   .onSource(bar)
702                   .onLine(8);
703             });
704   }
705 
706   @Test
testScopedAssistedInjection()707   public void testScopedAssistedInjection() {
708     Source foo =
709         CompilerTests.javaSource(
710             "test.Foo",
711             "package test;",
712             "",
713             "import dagger.assisted.Assisted;",
714             "import dagger.assisted.AssistedInject;",
715             "import dagger.assisted.AssistedFactory;",
716             "import javax.inject.Singleton;",
717             "",
718             "@Singleton",
719             "class Foo {",
720             "  @AssistedInject",
721             "  Foo(@Assisted int i) {}",
722             "",
723             "  @AssistedFactory",
724             "  interface Factory {",
725             "    Foo create(int i);",
726             "  }",
727             "}");
728 
729     CompilerTests.daggerCompiler(foo)
730         .withProcessingOptions(compilerMode.processorOptions())
731         .compile(
732             subject ->
733                 // Don't assert on the number of errors as Foo_Factory_Impl can also be created
734                 // and have errors from the missing Foo_Factory.
735                 // TODO(erichang): don't generate the factory impls if there are errors with the
736                 // assisted type
737                 subject
738                     .hasErrorContaining(
739                         "A type with an @AssistedInject-annotated constructor cannot be scoped")
740                     .onSource(foo)
741                     .onLine(8));
742   }
743 
744   @Test
testMultipleInjectAnnotations()745   public void testMultipleInjectAnnotations() {
746     Source foo =
747         CompilerTests.javaSource(
748             "test.Foo",
749             "package test;",
750             "",
751             "import dagger.assisted.Assisted;",
752             "import dagger.assisted.AssistedInject;",
753             "import javax.inject.Inject;",
754             "",
755             "class Foo {",
756             "  @Inject",
757             "  @AssistedInject",
758             "  Foo(@Assisted int i) {}",
759             "}");
760 
761     CompilerTests.daggerCompiler(foo)
762         .withProcessingOptions(compilerMode.processorOptions())
763         .compile(
764             subject -> {
765               subject.hasErrorCount(1);
766               subject.hasErrorContaining(
767                   "Constructors cannot be annotated with both @Inject and @AssistedInject");
768             });
769   }
770 
771   @Test
testAssistedInjectWithNoAssistedParametersIsNotInjectable()772   public void testAssistedInjectWithNoAssistedParametersIsNotInjectable() {
773     Source foo =
774         CompilerTests.javaSource(
775             "test.Foo",
776             "package test;",
777             "",
778             "import javax.inject.Inject;",
779             "",
780             "class Foo {",
781             "  @Inject",
782             "  Foo(Bar bar) {}",
783             "}");
784 
785     Source bar =
786         CompilerTests.javaSource(
787             "test.Bar",
788             "package test;",
789             "",
790             "import dagger.assisted.AssistedInject;",
791             "import javax.inject.Inject;",
792             "",
793             "class Bar {",
794             "  @AssistedInject",
795             "  Bar() {}",
796             "}");
797 
798     Source component =
799         CompilerTests.javaSource(
800             "test.FooComponent",
801             "package test;",
802             "",
803             "import dagger.Component;",
804             "",
805             "@Component",
806             "interface FooComponent {",
807             "  Foo foo();",
808             "}");
809 
810 
811     CompilerTests.daggerCompiler(foo, bar, component)
812         .withProcessingOptions(compilerMode.processorOptions())
813         .compile(
814             subject -> {
815               subject.hasErrorCount(2);
816               subject.hasErrorContaining(
817                       "Dagger does not support injecting @AssistedInject type, test.Bar. "
818                           + "Did you mean to inject its assisted factory type instead?")
819                   .onSource(foo)
820                   .onLine(7);
821               subject.hasErrorContaining(
822                   "\033[1;31m[Dagger/MissingBinding]\033[0m "
823                       + "Foo cannot be provided without an @Inject constructor or an "
824                       + "@Provides-annotated method.");
825             });
826   }
827 
828   @Test
testInaccessibleFoo()829   public void testInaccessibleFoo() {
830     Source foo =
831         CompilerTests.javaSource(
832             "test.subpackage.InaccessibleFoo",
833             "package test.subpackage;",
834             "",
835             "import dagger.assisted.Assisted;",
836             "import dagger.assisted.AssistedInject;",
837             "",
838             "class InaccessibleFoo {",
839             "  @AssistedInject InaccessibleFoo(@Assisted int i) {}",
840             "}");
841 
842     Source fooFactory =
843         CompilerTests.javaSource(
844             "test.subpackage.InaccessibleFooFactory",
845             "package test.subpackage;",
846             "",
847             "import dagger.assisted.AssistedFactory;",
848             "",
849             "@AssistedFactory",
850             "public interface InaccessibleFooFactory {",
851             "  InaccessibleFoo create(int i);",
852             "}");
853 
854     Source component =
855         CompilerTests.javaSource(
856             "test.FooFactoryComponent",
857             "package test;",
858             "",
859             "import dagger.Component;",
860             "import test.subpackage.InaccessibleFooFactory;",
861             "",
862             "@Component",
863             "interface FooFactoryComponent {",
864             "  InaccessibleFooFactory inaccessibleFooFactory();",
865             "}");
866 
867     CompilerTests.DaggerCompiler daggerCompiler =
868         CompilerTests.daggerCompiler(foo, fooFactory, component)
869             .withProcessingOptions(compilerMode.processorOptions());
870 
871     if (compilerMode == CompilerMode.FAST_INIT_MODE) {
872       // TODO(bcorso): Remove once we fix inaccessible assisted factory imlementation for fastInit.
873       daggerCompiler.compile(
874           subject -> {
875             // TODO(bcorso): We don't report the error count here because javac reports
876             // the error once, whereas ksp reports the error twice.
877             subject
878                 .hasErrorContaining(
879                     "test.subpackage.InaccessibleFoo is not public in test.subpackage; cannot be "
880                         + "accessed from outside package");
881           });
882     } else {
883       daggerCompiler.compile(subject -> subject.hasErrorCount(0));
884     }
885   }
886 
887   @Test
testAssistedFactoryMethodWithTypeParametersFails()888   public void testAssistedFactoryMethodWithTypeParametersFails() {
889     Source foo =
890         CompilerTests.javaSource(
891             "test.Foo",
892             "package test;",
893             "",
894             "import dagger.assisted.AssistedInject;",
895             "import dagger.assisted.AssistedFactory;",
896             "",
897             "class Foo<T> {",
898             "  @AssistedInject",
899             "  Foo() {}",
900             "",
901             "  @AssistedFactory",
902             "  interface FooFactory {",
903             "    <T> Foo<T> create();",
904             "  }",
905             "}");
906 
907     CompilerTests.daggerCompiler(foo)
908         .withProcessingOptions(compilerMode.processorOptions())
909         .compile(
910             subject -> {
911               subject.hasErrorCount(1);
912               subject.hasErrorContaining(
913                       "@AssistedFactory does not currently support type parameters in the creator "
914                           + "method.")
915                   .onSource(foo)
916                   .onLine(12);
917             });
918   }
919 }
920