Convert to anonymous function: do not suggest for suspend functions

#KT-37842 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-03-30 12:18:53 +09:00
committed by Yan Zhulanow
parent ded996bdf7
commit a4239afcb3
3 changed files with 27 additions and 3 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
@@ -22,7 +23,10 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunctionDescriptor
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -35,10 +39,16 @@ class LambdaToAnonymousFunctionIntention : SelfTargetingIntention<KtLambdaExpres
KotlinBundle.lazyMessage("convert.lambda.expression.to.anonymous.function")
), LowPriorityAction {
override fun isApplicableTo(element: KtLambdaExpression, caretOffset: Int): Boolean {
if (element.getStrictParentOfType<KtValueArgument>() == null) return false
if (element.getStrictParentOfType<KtFunction>()?.hasModifier(KtTokens.INLINE_KEYWORD) == true) return false
val descriptor = element.functionLiteral.descriptor as? AnonymousFunctionDescriptor ?: return false
val argument = element.getStrictParentOfType<KtValueArgument>() ?: return false
val call = argument.getStrictParentOfType<KtCallElement>() ?: return false
if (call.getStrictParentOfType<KtFunction>()?.hasModifier(KtTokens.INLINE_KEYWORD) == true) return false
val context = call.analyze(BodyResolveMode.PARTIAL)
if (call.getResolvedCall(context)?.getParameterForArgument(argument)?.type?.isSuspendFunctionType == true) return false
val descriptor =
context[BindingContext.DECLARATION_TO_DESCRIPTOR, element.functionLiteral] as? AnonymousFunctionDescriptor ?: return false
if (descriptor.valueParameters.any { it.name.isSpecial }) return false
val lastElement = element.functionLiteral.arrow ?: element.functionLiteral.lBrace
return caretOffset <= lastElement.endOffset
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: false
suspend fun sus(i: Int, block: suspend (Int) -> Unit) {
block(i)
}
suspend fun main() {
sus(1) {<caret>
}
}
@@ -10528,6 +10528,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/lambdaToAnonymousFunction/returnUnit.kt");
}
@TestMetadata("suspendFunction.kt")
public void testSuspendFunction() throws Exception {
runTest("idea/testData/intentions/lambdaToAnonymousFunction/suspendFunction.kt");
}
@TestMetadata("underscoreParameter.kt")
public void testUnderscoreParameter() throws Exception {
runTest("idea/testData/intentions/lambdaToAnonymousFunction/underscoreParameter.kt");