From 272ee252d8d4933f29093dd91f08c5bcc4600cec Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 24 Aug 2018 16:20:17 +0300 Subject: [PATCH] Report warning on "suspend {}"-like calls based on variable #KT-22892 Fixed --- .../LambdaWithSuspendModifierCallChecker.kt | 13 +++++++------ .../coroutines/nonModifierFormForBuiltIn.kt | 9 +++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LambdaWithSuspendModifierCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LambdaWithSuspendModifierCallChecker.kt index 76b13569351..de8f3c82adb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LambdaWithSuspendModifierCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LambdaWithSuspendModifierCallChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -23,18 +24,19 @@ object LambdaWithSuspendModifierCallChecker : CallChecker { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.candidateDescriptor val call = resolvedCall.call - val callName = call.referencedName() + val calleeName = call.referencedName() + val variableCalleeName = resolvedCall.safeAs()?.variableCall?.call?.referencedName() - if (callName != "suspend" && descriptor.name.asString() != "suspend") return + if (calleeName != "suspend" && variableCalleeName != "suspend" && descriptor.name.asString() != "suspend") return when (descriptor.fqNameOrNull()) { KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME -> { - if (!call.hasFormOfSuspendModifierForLambda() || call.explicitReceiver != null) { + if (calleeName != "suspend" || !call.hasFormOfSuspendModifierForLambda() || call.explicitReceiver != null) { context.trace.report(Errors.NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND.on(reportOn)) } } else -> { - if (call.hasFormOfSuspendModifierForLambda()) { + if ((calleeName == "suspend" || variableCalleeName == "suspend") && call.hasFormOfSuspendModifierForLambda()) { context.trace.report(Errors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND.on(reportOn)) } } @@ -42,8 +44,7 @@ object LambdaWithSuspendModifierCallChecker : CallChecker { } private fun Call.hasFormOfSuspendModifierForLambda() = - referencedName() == "suspend" - && !isCallableReference() + !isCallableReference() && typeArguments.isEmpty() && (hasNoArgumentListButDanglingLambdas() || isInfixWithRightLambda()) diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/nonModifierFormForBuiltIn.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/nonModifierFormForBuiltIn.kt index 34019060d2d..64c6e38e67b 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/nonModifierFormForBuiltIn.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/nonModifierFormForBuiltIn.kt @@ -34,3 +34,12 @@ fun bar() { @Target(AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) annotation class Ann + +fun main(suspend: WLambdaInvoke) { + + suspend {} +} + +class WLambdaInvoke { + operator fun invoke(l: () -> Unit) {} +}