@@ -10,10 +10,15 @@ import com.android.tools.lint.detector.api.Scope
10
10
import com.android.tools.lint.detector.api.Severity
11
11
import com.intellij.psi.PsiMember
12
12
import com.intellij.psi.impl.source.PsiClassReferenceType
13
+ import org.jetbrains.kotlin.psi.KtCallExpression
14
+ import org.jetbrains.kotlin.psi.psiUtil.parents
13
15
import org.jetbrains.uast.UCallExpression
14
16
import org.jetbrains.uast.UElement
15
17
import org.jetbrains.uast.UQualifiedReferenceExpression
16
18
import org.jetbrains.uast.USimpleNameReferenceExpression
19
+ import org.jetbrains.uast.getContainingUClass
20
+ import org.jetbrains.uast.toUElement
21
+ import org.jetbrains.uast.tryResolveNamed
17
22
18
23
class MaterialDesignInsteadOrbitDesignDetector : Detector (), Detector.UastScanner {
19
24
override fun getApplicableUastTypes (): List <Class <out UElement >> {
@@ -29,9 +34,24 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
29
34
override fun visitCallExpression (node : UCallExpression ) {
30
35
val name = node.methodName ? : return
31
36
val wrapperName = node.resolve()?.containingClass?.qualifiedName ? : return
32
- val packageName = wrapperName.substring( 0 , wrapperName.lastIndexOf( " . " ) )
37
+ val packageName = getPackageName( wrapperName)
33
38
val fqn = " $packageName .$name "
34
39
val (preferredName) = METHOD_NAMES .entries.firstOrNull { it.value.contains(fqn) } ? : return
40
+
41
+ // check the potential violation against our allowlist
42
+ val allowedEntry = METHOD_ALLOWLIST_IN_PARENT .entries.find { it.key.contains(fqn) }
43
+ if (allowedEntry != null ) {
44
+ val parentExpression = node.sourcePsi?.parents?.find { it is KtCallExpression }
45
+ val resolved = parentExpression.toUElement()?.tryResolveNamed()
46
+ val parentName = resolved?.name
47
+ val parentWrapper = resolved.toUElement()?.getContainingUClass()?.qualifiedName ? : " "
48
+ val parentPackage = getPackageName(parentWrapper)
49
+ val parentFqn = " $parentPackage .$parentName "
50
+ if (allowedEntry.value.find { parentFqn.contains(it) } != null ) {
51
+ return
52
+ }
53
+ }
54
+
35
55
reportIssue(context, node, " $packageName .$name " , preferredName)
36
56
}
37
57
@@ -66,6 +86,17 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
66
86
),
67
87
)
68
88
89
+ private val METHOD_ALLOWLIST_IN_PARENT = mapOf (
90
+ " androidx.compose.material.TextButton" to setOf (
91
+ " androidx.compose.material.AlertDialog" ,
92
+ " androidx.compose.material3.AlertDialog" ,
93
+ ),
94
+ " androidx.compose.material3.TextButton" to setOf (
95
+ " androidx.compose.material.AlertDialog" ,
96
+ " androidx.compose.material3.AlertDialog" ,
97
+ ),
98
+ )
99
+
69
100
private val METHOD_NAMES = mapOf (
70
101
" kiwi.orbit.compose.ui.controls.ButtonPrimary" to setOf (
71
102
" androidx.compose.material.Button" ,
@@ -191,5 +222,9 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
191
222
" Using $name instead of $preferredName " ,
192
223
)
193
224
}
225
+
226
+ private fun getPackageName (fullyQualifiedName : String ): String {
227
+ return fullyQualifiedName.substring(0 , fullyQualifiedName.lastIndexOf(" ." ))
228
+ }
194
229
}
195
230
}
0 commit comments