Skip to content

Commit 66da222

Browse files
authored
fix: support namedMethodReference (#682)
* fix: support namedMethodReference * fix: add one more test case
1 parent 9901c95 commit 66da222

File tree

2 files changed

+109
-11
lines changed

2 files changed

+109
-11
lines changed

lint/src/main/java/permissions/dispatcher/CallOnRequestPermissionsResultDetector.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package permissions.dispatcher;
22

3+
import androidx.annotation.Nullable;
4+
35
import com.android.tools.lint.client.api.UElementHandler;
46
import com.android.tools.lint.detector.api.Category;
57
import com.android.tools.lint.detector.api.Detector;
@@ -18,6 +20,7 @@
1820
import org.jetbrains.uast.UMethod;
1921
import org.jetbrains.uast.UQualifiedReferenceExpression;
2022
import org.jetbrains.uast.kotlin.KotlinUFunctionCallExpression;
23+
import org.jetbrains.uast.kotlin.KotlinUImplicitReturnExpression;
2124
import org.jetbrains.uast.kotlin.KotlinUQualifiedReferenceExpression;
2225
import org.jetbrains.uast.visitor.AbstractUastVisitor;
2326

@@ -91,6 +94,10 @@ public boolean visitMethod(UMethod node) {
9194
return true;
9295
}
9396

97+
private static boolean assertMethodName(@Nullable String name) {
98+
return "onRequestPermissionsResult".equals(name);
99+
}
100+
94101
private static boolean isGeneratedMethodCalled(UMethod method, String className, boolean isKotlin) {
95102
UExpression methodBody = method.getUastBody();
96103
if (methodBody == null) {
@@ -102,8 +109,15 @@ private static boolean isGeneratedMethodCalled(UMethod method, String className,
102109
for (UExpression expression : expressions) {
103110
if (isKotlin && expression instanceof KotlinUFunctionCallExpression) {
104111
KotlinUFunctionCallExpression functionalExpression = (KotlinUFunctionCallExpression) expression;
105-
if ("onRequestPermissionsResult".equals(functionalExpression.getMethodName())) {
106-
return true;
112+
return assertMethodName(functionalExpression.getMethodName());
113+
} else if (isKotlin && expression instanceof KotlinUImplicitReturnExpression) {
114+
KotlinUImplicitReturnExpression returnExpression =
115+
(KotlinUImplicitReturnExpression) expression;
116+
UExpression uExpression = returnExpression.returnExpression;
117+
if (uExpression instanceof KotlinUFunctionCallExpression) {
118+
KotlinUFunctionCallExpression uFunctionCallExpression =
119+
(KotlinUFunctionCallExpression) uExpression;
120+
return assertMethodName(uFunctionCallExpression.getMethodName());
107121
}
108122
}
109123

@@ -124,12 +138,10 @@ private static boolean isGeneratedMethodCalled(UMethod method, String className,
124138
}
125139

126140
if (isKotlin && referenceExpression instanceof KotlinUQualifiedReferenceExpression) {
127-
if ("onRequestPermissionsResult".equals(referenceExpression.getResolvedName())) {
128-
return true;
129-
}
141+
return assertMethodName(referenceExpression.getResolvedName());
130142
} else {
131143
String targetClassName = className + "PermissionsDispatcher";
132-
if (targetClassName.equals(receiverName) && "onRequestPermissionsResult".equals(referenceExpression.getResolvedName())) {
144+
if (targetClassName.equals(receiverName) && assertMethodName(referenceExpression.getResolvedName())) {
133145
return true;
134146
}
135147
}

lint/src/test/java/permissions/dispatcher/CallOnRequestPermissionsResultDetectorKtTest.kt

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
package permissions.dispatcher
22

3-
import org.intellij.lang.annotations.Language
4-
import org.junit.Test
5-
63
import com.android.tools.lint.checks.infrastructure.TestFiles.java
74
import com.android.tools.lint.checks.infrastructure.TestFiles.kt
85
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
6+
import org.intellij.lang.annotations.Language
7+
import org.junit.Test
98
import permissions.dispatcher.Utils.onNeedsPermission
109
import permissions.dispatcher.Utils.onRationaleAnnotation
1110
import permissions.dispatcher.Utils.runtimePermission
1211

1312
class CallOnRequestPermissionsResultDetectorKtTest {
14-
1513
@Test
1614
@Throws(Exception::class)
1715
fun callOnRequestPermissionsResultDetectorNoErrorForKotlin() {
@@ -20,7 +18,7 @@ class CallOnRequestPermissionsResultDetectorKtTest {
2018
2119
@RuntimePermissions
2220
class Foo : android.app.Activity {
23-
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
21+
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
2422
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
2523
onRequestPermissionsResult(requestCode, grantResults)
2624
}
@@ -54,6 +52,94 @@ class CallOnRequestPermissionsResultDetectorKtTest {
5452
.expectClean()
5553
}
5654

55+
@Test
56+
@Throws(Exception::class)
57+
fun callOnRequestPermissionsResultDetectorNoErrorWithNamedMethodReference() {
58+
@Language("kotlin") val foo = """
59+
package permissions.dispatcher
60+
61+
@RuntimePermissions
62+
class Foo : android.app.Activity {
63+
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
64+
onRequestPermissionsResult(requestCode, grantResults)
65+
66+
@NeedsPermission("Camera")
67+
fun showCamera() {
68+
}
69+
70+
@OnShowRationale("Camera")
71+
fun someMethod() {
72+
}
73+
}
74+
""".trimMargin()
75+
76+
@Language("kotlin") val generatedClass = """
77+
package permissions.dispatcher
78+
79+
fun Foo.onRequestPermissionsResult(requestCode: Int, grantResults: IntArray) {
80+
}
81+
""".trimMargin()
82+
83+
lint()
84+
.files(
85+
java(runtimePermission),
86+
java(onNeedsPermission),
87+
java(onRationaleAnnotation),
88+
kt(generatedClass),
89+
kt(foo))
90+
.issues(CallOnRequestPermissionsResultDetector.ISSUE)
91+
.run()
92+
.expectClean()
93+
}
94+
95+
@Test
96+
@Throws(Exception::class)
97+
fun callOnRequestPermissionsResultDetectorErrorWithWrongMethod() {
98+
@Language("kotlin") val foo = """
99+
package permissions.dispatcher
100+
101+
@RuntimePermissions
102+
class Foo : android.app.Activity {
103+
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
104+
hoge(requestCode, grantResults)
105+
106+
@NeedsPermission("Camera")
107+
fun showCamera() {
108+
}
109+
110+
@OnShowRationale("Camera")
111+
fun someMethod() {
112+
}
113+
}
114+
""".trimMargin()
115+
116+
@Language("kotlin") val generatedClass = """
117+
package permissions.dispatcher
118+
119+
fun Foo.hoge(requestCode: Int, grantResults: IntArray) {
120+
}
121+
""".trimMargin()
122+
123+
val expectedText = """
124+
|src/permissions/dispatcher/Foo.kt:5: Error: Generated onRequestPermissionsResult method not called [NeedOnRequestPermissionsResult]
125+
| override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
126+
| ^
127+
|1 errors, 0 warnings
128+
""".trimMargin()
129+
130+
lint()
131+
.files(
132+
java(runtimePermission),
133+
java(onNeedsPermission),
134+
java(onRationaleAnnotation),
135+
kt(foo))
136+
.issues(CallOnRequestPermissionsResultDetector.ISSUE)
137+
.run()
138+
.expect(expectedText)
139+
.expectErrorCount(1)
140+
.expectWarningCount(0)
141+
}
142+
57143
@Test
58144
@Throws(Exception::class)
59145
fun callOnRequestPermissionsResultDetector() {

0 commit comments

Comments
 (0)