From 4ad8d74847eae44f30f31bcf8199814e97112fac Mon Sep 17 00:00:00 2001 From: lexter Date: Mon, 4 Mar 2019 19:41:11 +0300 Subject: [PATCH] checking suspendCoroutine v2 --- gradlew | 0 .../android/CheckedExceptionsDetector.kt | 56 ++++++++++++++----- .../CheckedExceptionsCoroutinesClasses.kt | 22 ++++---- 3 files changed, 53 insertions(+), 25 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/lint-rules-android/src/main/java/com/thirdegg/lintrules/android/CheckedExceptionsDetector.kt b/lint-rules-android/src/main/java/com/thirdegg/lintrules/android/CheckedExceptionsDetector.kt index 65c7dcc..579a1b8 100644 --- a/lint-rules-android/src/main/java/com/thirdegg/lintrules/android/CheckedExceptionsDetector.kt +++ b/lint-rules-android/src/main/java/com/thirdegg/lintrules/android/CheckedExceptionsDetector.kt @@ -43,65 +43,91 @@ class CheckedExceptionsDetector : Detector(), Detector.UastScanner { override fun createUastHandler(context: JavaContext) = object:UElementHandler() { init { - println(context.uastFile?.asRecursiveLogString()) +// println(context.uastFile?.asRecursiveLogString()) } override fun visitCallExpression(node: UCallExpression) { val parrentNode = node - val method = parrentNode.resolve()?:return + val method = parrentNode.resolve() ?: return val uMethod = context.uastContext.getMethod(method) val haveTryCatch = ArrayList() - val tryException = findParrentByUast(parrentNode,UTryExpression::class.java) - if (tryException!=null) { + val tryException = findParrentByUast(parrentNode, UTryExpression::class.java) + if (tryException != null) { for (catchCause in tryException.catchClauses) { haveTryCatch.add(findExceptionClassName(catchCause)) } } - uMethod.accept(object:AbstractUastVisitor() { + uMethod.accept(object : AbstractUastVisitor() { override fun visitCallExpression(node: UCallExpression): Boolean { if (node.uastParent !is UCallExpression) return super.visitCallExpression(node) val parentResolve = (node.uastParent as UCallExpression).resolve() val resolve = node.resolve() - if (parentResolve?.containingClass?.qualifiedName != "kotlin.coroutines.Continuation" - && parentResolve?.containingClass?.qualifiedName != "com.thirdegg.lintrules.android.Continuation") + if (parentResolve?.containingClass?.qualifiedName?.contains("Continuation") != true) { return super.visitCallExpression(node) + } - if ((node.uastParent as UCallExpression?)?.methodName!="resumeWithException") return super.visitCallExpression(node) + if ((node.uastParent as UCallExpression?)?.methodName != "resumeWithException") + return super.visitCallExpression(node) + + val clazzName = resolve?.containingClass?.qualifiedName + ?: return super.visitCallExpression(node) + + if (haveTryCatch.contains(clazzName)) + return super.visitCallExpression(node) + + var superClass = resolve.containingClass?.superClass + while (superClass!=null) { + if (haveTryCatch.contains(superClass.qualifiedName)) + return super.visitCallExpression(node) + superClass = superClass.superClass + } - val clazzName = resolve?.containingClass?.qualifiedName?:return super.visitCallExpression(node) context.report(ISSUE_PATTERN, parrentNode, context.getNameLocation(parrentNode), "Exception not checked: $clazzName") + println(clazzName) + return super.visitCallExpression(node) } }) - uMethod.accept(object:AbstractUastVisitor() { + uMethod.accept(object : AbstractUastVisitor() { override fun visitThrowExpression(node: UThrowExpression): Boolean { - node.accept(object:AbstractUastVisitor() { + node.accept(object : AbstractUastVisitor() { + override fun visitCallExpression(node: UCallExpression): Boolean { if (node is KotlinUFunctionCallExpression) { //TODO kotlin.Exception() not catch val clazz = node.resolve() - val clazzName = clazz?.containingClass?.qualifiedName - if (clazzName==null || haveTryCatch.contains(clazzName)) return super.visitCallExpression(node) - context.report(ISSUE_PATTERN, parrentNode, context.getNameLocation(parrentNode), - "Exception not checked: $clazzName") + val clazzName = clazz?.containingClass?.qualifiedName?:return super.visitCallExpression(node) + if (haveTryCatch.contains(clazzName)) return super.visitCallExpression(node) + + var superClass = clazz.containingClass?.superClass + while (superClass!=null) { + if (haveTryCatch.contains(superClass?.qualifiedName)) + return super.visitCallExpression(node) + superClass = superClass?.superClass + } + + context.report(ISSUE_PATTERN, parrentNode, context.getNameLocation(parrentNode),"Exception not checked: $clazzName") } return super.visitCallExpression(node) } + }) + return super.visitThrowExpression(node) } }) } + } } \ No newline at end of file diff --git a/lint-rules-android/src/test/java/com/thirdegg/lintrules/android/CheckedExceptionsCoroutinesClasses.kt b/lint-rules-android/src/test/java/com/thirdegg/lintrules/android/CheckedExceptionsCoroutinesClasses.kt index 5f03f06..409e761 100644 --- a/lint-rules-android/src/test/java/com/thirdegg/lintrules/android/CheckedExceptionsCoroutinesClasses.kt +++ b/lint-rules-android/src/test/java/com/thirdegg/lintrules/android/CheckedExceptionsCoroutinesClasses.kt @@ -13,7 +13,7 @@ object CheckedExceptionsCoroutinesClasses { callback.onResponse(Response()) } - fun await():String = Helper.suspendCoroutine { cont:Continuation -> + fun await():String = suspendCoroutine { cont -> enqueue(object: Callback { override fun onResponse(response: Response) { @@ -87,7 +87,6 @@ object CheckedExceptionsCoroutinesClasses { package com.thirdegg.lintrules.android - import java.lang.Exception class NotAuthorizedException(error: String):Exception(error) class ForbiddenException(error: String):Exception(error) @@ -105,7 +104,11 @@ object CheckedExceptionsCoroutinesClasses { class Main { fun check() { - Call().await() + try { + Call().await() + } catch (e:Exception) { + e.printStackTrace() + } } } @@ -130,16 +133,15 @@ object CheckedExceptionsCoroutinesClasses { } } - object Helper { - - fun suspendCoroutine(block: (count:Continuation) -> Unit): String { - val cont = Continuation() - block(cont) - return cont.result - } + suspend inline fun suspendCoroutine(crossinline block: (Continuation) -> Unit): String { + val cont = Continuation() + block(cont) + return cont.result } + + """).indented() } \ No newline at end of file