• 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.hilt.android.processor.internal.viewmodel
18 
19 import com.google.testing.compile.CompilationSubject.assertThat
20 import com.google.testing.compile.Compiler
21 import org.junit.Test
22 import org.junit.runner.RunWith
23 import org.junit.runners.JUnit4
24 
25 @RunWith(JUnit4::class)
26 class ViewModelGeneratorTest {
27 
compilernull28   private fun compiler(): Compiler = Compiler.javac().withProcessors(ViewModelProcessor())
29 
30   @Test
31   fun verifyModule_noArg() {
32     val myViewModel = """
33         package dagger.hilt.android.test;
34 
35         import dagger.hilt.android.lifecycle.HiltViewModel;
36         import androidx.lifecycle.ViewModel;
37         import javax.inject.Inject;
38 
39         @HiltViewModel
40         class MyViewModel extends ViewModel {
41             @Inject
42             MyViewModel() { }
43         }
44         """.toJFO("dagger.hilt.android.test.MyViewModel")
45 
46     val expected = """
47         package dagger.hilt.android.test;
48 
49         import androidx.lifecycle.ViewModel;
50         import dagger.Binds;
51         import dagger.Module;
52         import dagger.Provides;
53         import dagger.hilt.InstallIn;
54         import dagger.hilt.android.components.ActivityRetainedComponent;
55         import dagger.hilt.android.components.ViewModelComponent;
56         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
57         import dagger.hilt.codegen.OriginatingElement;
58         import dagger.multibindings.IntoMap;
59         import dagger.multibindings.IntoSet;
60         import dagger.multibindings.StringKey;
61         import java.lang.String;
62         import $GENERATED_TYPE
63 
64         $GENERATED_ANNOTATION
65         @OriginatingElement(
66             topLevelClass = MyViewModel.class
67         )
68         public final class MyViewModel_HiltModules {
69           private MyViewModel_HiltModules() {
70           }
71 
72           @Module
73           @InstallIn(ViewModelComponent.class)
74           public static abstract class BindsModule {
75             @Binds
76             @IntoMap
77             @StringKey("dagger.hilt.android.test.MyViewModel")
78             @HiltViewModelMap
79             public abstract ViewModel binds(MyViewModel vm);
80           }
81 
82           @Module
83           @InstallIn(ActivityRetainedComponent.class)
84           public static final class KeyModule {
85             private KeyModule() {
86             }
87 
88             @Provides
89             @IntoSet
90             @HiltViewModelMap.KeySet
91             public static String provide() {
92               return "dagger.hilt.android.test.MyViewModel";
93             }
94           }
95         }
96         """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
97 
98     val compilation = compiler()
99       .compile(myViewModel)
100     assertThat(compilation).apply {
101       succeeded()
102       generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
103         .hasSourceEquivalentTo(expected)
104     }
105   }
106 
107   @Test
verifyModule_savedStateOnlyArgnull108   fun verifyModule_savedStateOnlyArg() {
109     val myViewModel = """
110         package dagger.hilt.android.test;
111 
112         import dagger.hilt.android.lifecycle.HiltViewModel;
113         import androidx.lifecycle.ViewModel;
114         import androidx.lifecycle.SavedStateHandle;
115         import javax.inject.Inject;
116 
117         @HiltViewModel
118         class MyViewModel extends ViewModel {
119             @Inject
120             MyViewModel(SavedStateHandle savedState) { }
121         }
122         """.toJFO("dagger.hilt.android.test.MyViewModel")
123 
124     val expected = """
125         package dagger.hilt.android.test;
126 
127         import androidx.lifecycle.ViewModel;
128         import dagger.Binds;
129         import dagger.Module;
130         import dagger.Provides;
131         import dagger.hilt.InstallIn;
132         import dagger.hilt.android.components.ActivityRetainedComponent;
133         import dagger.hilt.android.components.ViewModelComponent;
134         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
135         import dagger.hilt.codegen.OriginatingElement;
136         import dagger.multibindings.IntoMap;
137         import dagger.multibindings.IntoSet;
138         import dagger.multibindings.StringKey;
139         import java.lang.String;
140         import $GENERATED_TYPE
141 
142         $GENERATED_ANNOTATION
143         @OriginatingElement(
144             topLevelClass = MyViewModel.class
145         )
146         public final class MyViewModel_HiltModules {
147           private MyViewModel_HiltModules() {
148           }
149 
150           @Module
151           @InstallIn(ViewModelComponent.class)
152           public static abstract class BindsModule {
153             @Binds
154             @IntoMap
155             @StringKey("dagger.hilt.android.test.MyViewModel")
156             @HiltViewModelMap
157             public abstract ViewModel binds(MyViewModel vm);
158           }
159 
160           @Module
161           @InstallIn(ActivityRetainedComponent.class)
162           public static final class KeyModule {
163             private KeyModule() {
164             }
165 
166             @Provides
167             @IntoSet
168             @HiltViewModelMap.KeySet
169             public static String provide() {
170               return "dagger.hilt.android.test.MyViewModel";
171             }
172           }
173         }
174         """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
175 
176     val compilation = compiler()
177       .compile(myViewModel)
178     assertThat(compilation).apply {
179       succeeded()
180       generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
181         .hasSourceEquivalentTo(expected)
182     }
183   }
184 
185   @Test
verifyModule_mixedArgsnull186   fun verifyModule_mixedArgs() {
187     val foo = """
188         package dagger.hilt.android.test;
189 
190         public class Foo { }
191         """.toJFO("dagger.hilt.android.test.Foo")
192 
193     val myViewModel = """
194         package dagger.hilt.android.test;
195 
196         import dagger.hilt.android.lifecycle.HiltViewModel;
197         import androidx.lifecycle.ViewModel;
198         import androidx.lifecycle.SavedStateHandle;
199         import java.lang.String;
200         import javax.inject.Inject;
201 
202         @HiltViewModel
203         class MyViewModel extends ViewModel {
204             @Inject
205             MyViewModel(String s, Foo f, SavedStateHandle savedState, long l) { }
206         }
207         """.toJFO("dagger.hilt.android.test.MyViewModel")
208 
209     val expected = """
210         package dagger.hilt.android.test;
211 
212         import androidx.lifecycle.ViewModel;
213         import dagger.Binds;
214         import dagger.Module;
215         import dagger.Provides;
216         import dagger.hilt.InstallIn;
217         import dagger.hilt.android.components.ActivityRetainedComponent;
218         import dagger.hilt.android.components.ViewModelComponent;
219         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
220         import dagger.hilt.codegen.OriginatingElement;
221         import dagger.multibindings.IntoMap;
222         import dagger.multibindings.IntoSet;
223         import dagger.multibindings.StringKey;
224         import java.lang.String;
225         import $GENERATED_TYPE
226 
227         $GENERATED_ANNOTATION
228         @OriginatingElement(
229             topLevelClass = MyViewModel.class
230         )
231         public final class MyViewModel_HiltModules {
232           private MyViewModel_HiltModules() {
233           }
234 
235           @Module
236           @InstallIn(ViewModelComponent.class)
237           public static abstract class BindsModule {
238             @Binds
239             @IntoMap
240             @StringKey("dagger.hilt.android.test.MyViewModel")
241             @HiltViewModelMap
242             public abstract ViewModel binds(MyViewModel vm);
243           }
244 
245           @Module
246           @InstallIn(ActivityRetainedComponent.class)
247           public static final class KeyModule {
248             private KeyModule() {
249             }
250 
251             @Provides
252             @IntoSet
253             @HiltViewModelMap.KeySet
254             public static String provide() {
255               return "dagger.hilt.android.test.MyViewModel";
256             }
257           }
258         }
259         """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
260 
261     val compilation = compiler()
262       .compile(foo, myViewModel)
263     assertThat(compilation).apply {
264       succeeded()
265       generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
266         .hasSourceEquivalentTo(expected)
267     }
268   }
269 
270   @Test
verifyModule_mixedAndProviderArgsnull271   fun verifyModule_mixedAndProviderArgs() {
272     val foo = """
273         package dagger.hilt.android.test;
274 
275         public class Foo { }
276         """.toJFO("dagger.hilt.android.test.Foo")
277 
278     val myViewModel = """
279         package dagger.hilt.android.test;
280 
281         import dagger.hilt.android.lifecycle.HiltViewModel;
282         import androidx.lifecycle.ViewModel;
283         import androidx.lifecycle.SavedStateHandle;
284         import java.lang.String;
285         import javax.inject.Inject;
286         import javax.inject.Provider;
287 
288         @HiltViewModel
289         class MyViewModel extends ViewModel {
290             @Inject
291             MyViewModel(String s, Provider<Foo> f, SavedStateHandle savedState) { }
292         }
293         """.toJFO("dagger.hilt.android.test.MyViewModel")
294 
295     val expected = """
296         package dagger.hilt.android.test;
297 
298         import androidx.lifecycle.ViewModel;
299         import dagger.Binds;
300         import dagger.Module;
301         import dagger.Provides;
302         import dagger.hilt.InstallIn;
303         import dagger.hilt.android.components.ActivityRetainedComponent;
304         import dagger.hilt.android.components.ViewModelComponent;
305         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
306         import dagger.hilt.codegen.OriginatingElement;
307         import dagger.multibindings.IntoMap;
308         import dagger.multibindings.IntoSet;
309         import dagger.multibindings.StringKey;
310         import java.lang.String;
311         import $GENERATED_TYPE;
312 
313         $GENERATED_ANNOTATION
314         @OriginatingElement(
315             topLevelClass = MyViewModel.class
316         )
317         public final class MyViewModel_HiltModules {
318           private MyViewModel_HiltModules() {
319           }
320 
321           @Module
322           @InstallIn(ViewModelComponent.class)
323           public static abstract class BindsModule {
324             @Binds
325             @IntoMap
326             @StringKey("dagger.hilt.android.test.MyViewModel")
327             @HiltViewModelMap
328             public abstract ViewModel binds(MyViewModel vm);
329           }
330 
331           @Module
332           @InstallIn(ActivityRetainedComponent.class)
333           public static final class KeyModule {
334             private KeyModule() {
335             }
336 
337             @Provides
338             @IntoSet
339             @HiltViewModelMap.KeySet
340             public static String provide() {
341               return "dagger.hilt.android.test.MyViewModel";
342             }
343           }
344         }
345         """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
346 
347     val compilation = compiler()
348       .compile(foo, myViewModel)
349     assertThat(compilation).apply {
350       succeeded()
351       generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
352         .hasSourceEquivalentTo(expected)
353     }
354   }
355 
356   @Test
verifyModule_qualifiedArgsnull357   fun verifyModule_qualifiedArgs() {
358     val myQualifier = """
359         package dagger.hilt.android.test;
360 
361         import javax.inject.Qualifier;
362 
363         @Qualifier
364         public @interface MyQualifier { }
365         """.toJFO("dagger.hilt.android.test.MyQualifier")
366 
367     val myViewModel = """
368         package dagger.hilt.android.test;
369 
370         import dagger.hilt.android.lifecycle.HiltViewModel;
371         import androidx.lifecycle.ViewModel;
372         import androidx.lifecycle.SavedStateHandle;
373         import java.lang.Long;
374         import java.lang.String;
375         import javax.inject.Inject;
376         import javax.inject.Named;
377         import javax.inject.Provider;
378 
379         @HiltViewModel
380         class MyViewModel extends ViewModel {
381             @Inject
382             MyViewModel(@Named("TheString") String s, @MyQualifier Provider<Long> l,
383                     SavedStateHandle savedState) {
384             }
385         }
386         """.toJFO("dagger.hilt.android.test.MyViewModel")
387 
388     val expected = """
389         package dagger.hilt.android.test;
390 
391         import androidx.lifecycle.ViewModel;
392         import dagger.Binds;
393         import dagger.Module;
394         import dagger.Provides;
395         import dagger.hilt.InstallIn;
396         import dagger.hilt.android.components.ActivityRetainedComponent;
397         import dagger.hilt.android.components.ViewModelComponent;
398         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
399         import dagger.hilt.codegen.OriginatingElement;
400         import dagger.multibindings.IntoMap;
401         import dagger.multibindings.IntoSet;
402         import dagger.multibindings.StringKey;
403         import java.lang.String;
404         import $GENERATED_TYPE;
405 
406         $GENERATED_ANNOTATION
407         @OriginatingElement(
408             topLevelClass = MyViewModel.class
409         )
410         public final class MyViewModel_HiltModules {
411           private MyViewModel_HiltModules() {
412           }
413 
414           @Module
415           @InstallIn(ViewModelComponent.class)
416           public static abstract class BindsModule {
417             @Binds
418             @IntoMap
419             @StringKey("dagger.hilt.android.test.MyViewModel")
420             @HiltViewModelMap
421             public abstract ViewModel binds(MyViewModel vm);
422           }
423 
424           @Module
425           @InstallIn(ActivityRetainedComponent.class)
426           public static final class KeyModule {
427             private KeyModule() {
428             }
429 
430             @Provides
431             @IntoSet
432             @HiltViewModelMap.KeySet
433             public static String provide() {
434               return "dagger.hilt.android.test.MyViewModel";
435             }
436           }
437         }
438         """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
439 
440     val compilation = compiler()
441       .compile(myQualifier, myViewModel)
442     assertThat(compilation).apply {
443       succeeded()
444       generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
445         .hasSourceEquivalentTo(expected)
446     }
447   }
448 
449   @Test
verifyInnerClassnull450   fun verifyInnerClass() {
451     val viewModel = """
452         package dagger.hilt.android.test;
453 
454         import dagger.hilt.android.lifecycle.HiltViewModel;
455         import androidx.lifecycle.ViewModel;
456         import javax.inject.Inject;
457 
458         class Outer {
459             @HiltViewModel
460             static class InnerViewModel extends ViewModel {
461                 @Inject
462                 InnerViewModel() { }
463             }
464         }
465         """.toJFO("dagger.hilt.android.test.Outer")
466 
467     val expectedModule = """
468         package dagger.hilt.android.test;
469 
470         import androidx.lifecycle.ViewModel;
471         import dagger.Binds;
472         import dagger.Module;
473         import dagger.Provides;
474         import dagger.hilt.InstallIn;
475         import dagger.hilt.android.components.ActivityRetainedComponent;
476         import dagger.hilt.android.components.ViewModelComponent;
477         import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
478         import dagger.hilt.codegen.OriginatingElement;
479         import dagger.multibindings.IntoMap;
480         import dagger.multibindings.IntoSet;
481         import dagger.multibindings.StringKey;
482         import java.lang.String;
483         import $GENERATED_TYPE
484 
485         $GENERATED_ANNOTATION
486         @OriginatingElement(
487             topLevelClass = Outer.class
488         )
489         public final class Outer_InnerViewModel_HiltModules {
490           private Outer_InnerViewModel_HiltModules() {
491           }
492 
493           @Module
494           @InstallIn(ViewModelComponent.class)
495           public static abstract class BindsModule {
496             @Binds
497             @IntoMap
498             @StringKey("dagger.hilt.android.test.Outer${'$'}InnerViewModel")
499             @HiltViewModelMap
500             public abstract ViewModel binds(Outer.InnerViewModel vm);
501           }
502 
503           @Module
504           @InstallIn(ActivityRetainedComponent.class)
505           public static final class KeyModule {
506             private KeyModule() {
507             }
508 
509             @Provides
510             @IntoSet
511             @HiltViewModelMap.KeySet
512             public static String provide() {
513               return "dagger.hilt.android.test.Outer${'$'}InnerViewModel";
514             }
515           }
516         }
517         """.toJFO("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
518 
519     val compilation = compiler()
520       .compile(viewModel)
521     assertThat(compilation).apply {
522       succeeded()
523       generatedSourceFile("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
524         .hasSourceEquivalentTo(expectedModule)
525     }
526   }
527 }
528