Skip to content

Commit

Permalink
fix: support namedMethodReference (#682)
Browse files Browse the repository at this point in the history
* fix: support namedMethodReference

* fix: add one more test case
  • Loading branch information
hotchemi authored Aug 30, 2020
1 parent 9901c95 commit 66da222
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package permissions.dispatcher;

import androidx.annotation.Nullable;

import com.android.tools.lint.client.api.UElementHandler;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Detector;
Expand All @@ -18,6 +20,7 @@
import org.jetbrains.uast.UMethod;
import org.jetbrains.uast.UQualifiedReferenceExpression;
import org.jetbrains.uast.kotlin.KotlinUFunctionCallExpression;
import org.jetbrains.uast.kotlin.KotlinUImplicitReturnExpression;
import org.jetbrains.uast.kotlin.KotlinUQualifiedReferenceExpression;
import org.jetbrains.uast.visitor.AbstractUastVisitor;

Expand Down Expand Up @@ -91,6 +94,10 @@ public boolean visitMethod(UMethod node) {
return true;
}

private static boolean assertMethodName(@Nullable String name) {
return "onRequestPermissionsResult".equals(name);
}

private static boolean isGeneratedMethodCalled(UMethod method, String className, boolean isKotlin) {
UExpression methodBody = method.getUastBody();
if (methodBody == null) {
Expand All @@ -102,8 +109,15 @@ private static boolean isGeneratedMethodCalled(UMethod method, String className,
for (UExpression expression : expressions) {
if (isKotlin && expression instanceof KotlinUFunctionCallExpression) {
KotlinUFunctionCallExpression functionalExpression = (KotlinUFunctionCallExpression) expression;
if ("onRequestPermissionsResult".equals(functionalExpression.getMethodName())) {
return true;
return assertMethodName(functionalExpression.getMethodName());
} else if (isKotlin && expression instanceof KotlinUImplicitReturnExpression) {
KotlinUImplicitReturnExpression returnExpression =
(KotlinUImplicitReturnExpression) expression;
UExpression uExpression = returnExpression.returnExpression;
if (uExpression instanceof KotlinUFunctionCallExpression) {
KotlinUFunctionCallExpression uFunctionCallExpression =
(KotlinUFunctionCallExpression) uExpression;
return assertMethodName(uFunctionCallExpression.getMethodName());
}
}

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

if (isKotlin && referenceExpression instanceof KotlinUQualifiedReferenceExpression) {
if ("onRequestPermissionsResult".equals(referenceExpression.getResolvedName())) {
return true;
}
return assertMethodName(referenceExpression.getResolvedName());
} else {
String targetClassName = className + "PermissionsDispatcher";
if (targetClassName.equals(receiverName) && "onRequestPermissionsResult".equals(referenceExpression.getResolvedName())) {
if (targetClassName.equals(receiverName) && assertMethodName(referenceExpression.getResolvedName())) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package permissions.dispatcher

import org.intellij.lang.annotations.Language
import org.junit.Test

import com.android.tools.lint.checks.infrastructure.TestFiles.java
import com.android.tools.lint.checks.infrastructure.TestFiles.kt
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
import org.intellij.lang.annotations.Language
import org.junit.Test
import permissions.dispatcher.Utils.onNeedsPermission
import permissions.dispatcher.Utils.onRationaleAnnotation
import permissions.dispatcher.Utils.runtimePermission

class CallOnRequestPermissionsResultDetectorKtTest {

@Test
@Throws(Exception::class)
fun callOnRequestPermissionsResultDetectorNoErrorForKotlin() {
Expand All @@ -20,7 +18,7 @@ class CallOnRequestPermissionsResultDetectorKtTest {
@RuntimePermissions
class Foo : android.app.Activity {
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
onRequestPermissionsResult(requestCode, grantResults)
}
Expand Down Expand Up @@ -54,6 +52,94 @@ class CallOnRequestPermissionsResultDetectorKtTest {
.expectClean()
}

@Test
@Throws(Exception::class)
fun callOnRequestPermissionsResultDetectorNoErrorWithNamedMethodReference() {
@Language("kotlin") val foo = """
package permissions.dispatcher
@RuntimePermissions
class Foo : android.app.Activity {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
onRequestPermissionsResult(requestCode, grantResults)
@NeedsPermission("Camera")
fun showCamera() {
}
@OnShowRationale("Camera")
fun someMethod() {
}
}
""".trimMargin()

@Language("kotlin") val generatedClass = """
package permissions.dispatcher
fun Foo.onRequestPermissionsResult(requestCode: Int, grantResults: IntArray) {
}
""".trimMargin()

lint()
.files(
java(runtimePermission),
java(onNeedsPermission),
java(onRationaleAnnotation),
kt(generatedClass),
kt(foo))
.issues(CallOnRequestPermissionsResultDetector.ISSUE)
.run()
.expectClean()
}

@Test
@Throws(Exception::class)
fun callOnRequestPermissionsResultDetectorErrorWithWrongMethod() {
@Language("kotlin") val foo = """
package permissions.dispatcher
@RuntimePermissions
class Foo : android.app.Activity {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
hoge(requestCode, grantResults)
@NeedsPermission("Camera")
fun showCamera() {
}
@OnShowRationale("Camera")
fun someMethod() {
}
}
""".trimMargin()

@Language("kotlin") val generatedClass = """
package permissions.dispatcher
fun Foo.hoge(requestCode: Int, grantResults: IntArray) {
}
""".trimMargin()

val expectedText = """
|src/permissions/dispatcher/Foo.kt:5: Error: Generated onRequestPermissionsResult method not called [NeedOnRequestPermissionsResult]
| override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) =
| ^
|1 errors, 0 warnings
""".trimMargin()

lint()
.files(
java(runtimePermission),
java(onNeedsPermission),
java(onRationaleAnnotation),
kt(foo))
.issues(CallOnRequestPermissionsResultDetector.ISSUE)
.run()
.expect(expectedText)
.expectErrorCount(1)
.expectWarningCount(0)
}

@Test
@Throws(Exception::class)
fun callOnRequestPermissionsResultDetector() {
Expand Down

0 comments on commit 66da222

Please sign in to comment.