xref: /aosp_15_r20/external/dagger2/javatests/dagger/lint/DaggerKotlinIssueDetectorTest.kt (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
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 package dagger.lint
17 
18 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
19 import com.android.tools.lint.checks.infrastructure.TestMode
20 import com.android.tools.lint.detector.api.Detector
21 import com.android.tools.lint.detector.api.Issue
22 import org.junit.Test
23 import org.junit.runner.RunWith
24 import org.junit.runners.JUnit4
25 
26 @Suppress("UnstableApiUsage")
27 @RunWith(JUnit4::class)
28 class DaggerKotlinIssueDetectorTest : LintDetectorTest() {
29 
30   private companion object {
31     private val javaxInjectStubs = kotlin(
32       """
33         package javax.inject
34 
35         annotation class Inject
36         annotation class Qualifier
37       """
38     ).indented()
39 
40     private val daggerStubs = kotlin(
41       """
42         package dagger
43 
44         annotation class Provides
45         annotation class Module
46       """
47     ).indented()
48 
49     // For some reason in Bazel the stdlib dependency on the classpath isn't visible to the
50     // LintTestTask, so we just include it ourselves here for now.
51     private val jvmStaticStubs = kotlin(
52       """
53         package kotlin.jvm
54 
55         annotation class JvmStatic
56       """
57     ).indented()
58   }
59 
getDetectornull60   override fun getDetector(): Detector = DaggerKotlinIssueDetector()
61 
62   override fun getIssues(): List<Issue> = DaggerKotlinIssueDetector.issues
63 
64   @Test
65   fun simpleSmokeTestForQualifiersAndProviders() {
66     lint()
67       .allowMissingSdk()
68       .files(
69         javaxInjectStubs,
70         daggerStubs,
71         jvmStaticStubs,
72         kotlin(
73           """
74           package foo
75           import javax.inject.Inject
76           import javax.inject.Qualifier
77           import kotlin.jvm.JvmStatic
78           import dagger.Provides
79           import dagger.Module
80 
81           @Qualifier
82           annotation class MyQualifier
83 
84           class InjectedTest {
85             // This should fail because of `:field`
86             @Inject
87             @field:MyQualifier
88             lateinit var prop: String
89 
90             // This is fine!
91             @Inject
92             @MyQualifier
93             lateinit var prop2: String
94           }
95 
96           @Module
97           object ObjectModule {
98             // This should fail because it uses `@JvmStatic`
99             @JvmStatic
100             @Provides
101             fun provideFoo(): String {
102 
103             }
104 
105             // This is fine!
106             @Provides
107             fun provideBar(): String {
108 
109             }
110           }
111 
112           @Module
113           class ClassModule {
114             companion object {
115               // This should fail because the companion object is part of ClassModule, so this is unnecessary.
116               @JvmStatic
117               @Provides
118               fun provideBaz(): String {
119 
120               }
121             }
122           }
123 
124           @Module
125           class ClassModuleQualified {
126             companion object {
127               // This should fail because the companion object is part of ClassModule, so this is unnecessary.
128               // This specifically tests a fully qualified annotation
129               @kotlin.jvm.JvmStatic
130               @Provides
131               fun provideBaz(): String {
132 
133               }
134             }
135           }
136 
137           @Module
138           class ClassModule2 {
139             // This should fail because the companion object is part of ClassModule
140             @Module
141             companion object {
142               @Provides
143               fun provideBaz(): String {
144 
145               }
146             }
147           }
148 
149           @Module
150           class ClassModule2Qualified {
151             // This should fail because the companion object is part of ClassModule
152             // This specifically tests a fully qualified annotation
153             @dagger.Module
154             companion object {
155               @Provides
156               fun provideBaz(): String {
157 
158               }
159             }
160           }
161 
162           // This is correct as of Dagger 2.26!
163           @Module
164           class ClassModule3 {
165             companion object {
166               @Provides
167               fun provideBaz(): String {
168 
169               }
170             }
171           }
172 
173           class ClassModule4 {
174             // This is should fail because this should be extracted to a standalone object.
175             @Module
176             companion object {
177               @Provides
178               fun provideBaz(): String {
179 
180               }
181             }
182           }
183         """
184         ).indented()
185       )
186       .allowCompilationErrors(false)
187       // Unlikely that @JvmStatic would be aliased, so skipping these modes.
188       .skipTestModes(TestMode.TYPE_ALIAS, TestMode.IMPORT_ALIAS)
189       .run()
190       .expect(
191         """
192         src/foo/MyQualifier.kt:14: Warning: Redundant 'field:' used for Dagger qualifier annotation. [FieldSiteTargetOnQualifierAnnotation]
193           @field:MyQualifier
194           ~~~~~~~~~~~~~~~~~~
195         src/foo/MyQualifier.kt:26: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
196           @JvmStatic
197           ~~~~~~~~~~
198         src/foo/MyQualifier.kt:43: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
199             @JvmStatic
200             ~~~~~~~~~~
201         src/foo/MyQualifier.kt:56: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
202             @kotlin.jvm.JvmStatic
203             ~~~~~~~~~~~~~~~~~~~~~
204         src/foo/MyQualifier.kt:66: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
205           // This should fail because the companion object is part of ClassModule
206           ^
207         src/foo/MyQualifier.kt:78: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
208           // This should fail because the companion object is part of ClassModule
209           ^
210         src/foo/MyQualifier.kt:101: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
211           // This is should fail because this should be extracted to a standalone object.
212           ^
213         0 errors, 7 warnings
214         """.trimIndent()
215       )
216       .expectFixDiffs(
217         """
218         Fix for src/foo/MyQualifier.kt line 14: Remove 'field:':
219         @@ -14 +14
220         -   @field:MyQualifier
221         +   @MyQualifier
222         Fix for src/foo/MyQualifier.kt line 26: Remove @JvmStatic:
223         @@ -26 +26
224         -   @JvmStatic
225         +
226         Fix for src/foo/MyQualifier.kt line 43: Remove @JvmStatic:
227         @@ -43 +43
228         -     @JvmStatic
229         +
230         Fix for src/foo/MyQualifier.kt line 56: Remove @JvmStatic:
231         @@ -56 +56
232         -     @kotlin.jvm.JvmStatic
233         +
234         Fix for src/foo/MyQualifier.kt line 66: Remove @Module:
235         @@ -67 +67
236         -   @Module
237         +
238         Fix for src/foo/MyQualifier.kt line 78: Remove @Module:
239         @@ -80 +80
240         -   @dagger.Module
241         +
242         Fix for src/foo/MyQualifier.kt line 101: Remove @Module:
243         @@ -102 +102
244         -   @Module
245         +
246         """.trimIndent()
247       )
248   }
249 }
250