From b008e6c9be057f8a1bdeee960059add6435a216a Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 29 Jan 2020 14:15:57 +0900 Subject: [PATCH] SimplifiableCallChainInspection: don't report if suspend function cannot be called correctly #KT-23934 Fixed --- .../collections/AbstractCallChainChecker.kt | 3 ++- .../SimplifiableCallChainInspection.kt | 14 ++++++++++++-- .../joinToStringWithSuspendFunctionCall.kt | 8 ++++++++ .../joinToWithSuspendFunctionCall.kt | 9 +++++++++ .../mapNotNullWithSuspendFunctionCall.kt | 7 +++++++ .../mapNotNullWithSuspendFunctionCall.kt.after | 7 +++++++ .../inspections/LocalInspectionTestGenerated.java | 15 +++++++++++++++ 7 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithSuspendFunctionCall.kt create mode 100644 idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithSuspendFunctionCall.kt create mode 100644 idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt create mode 100644 idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt index 4cb60b7779e..1d184a57c29 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt @@ -68,7 +68,8 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() { @NonNls val secondFqName: String, @NonNls val replacement: String, @NonNls val additionalArgument: String? = null, - val withNotNullAssertion: Boolean = false + val withNotNullAssertion: Boolean = false, + val enableSuspendFunctionCall: Boolean = true ) { private fun String.convertToShort() = takeLastWhile { it != '.' } diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt index 4ab6161ee0e..c3d8734cf64 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt @@ -7,13 +7,17 @@ package org.jetbrains.kotlin.idea.inspections.collections import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder +import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.qualifiedExpressionVisitor import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf @@ -36,6 +40,12 @@ class SimplifiableCallChainInspection : AbstractCallChainChecker() { } ) return@check false } + if (!conversion.enableSuspendFunctionCall) { + val isCallingSuspendFunction = firstResolvedCall.call.callElement.anyDescendantOfType { + it.getResolvedCall(context)?.resultingDescriptor?.isSuspend == true + } + if (isCallingSuspendFunction) return@check false + } true } ?: return @@ -99,8 +109,8 @@ class SimplifiableCallChainInspection : AbstractCallChainChecker() { Conversion("kotlin.text.filter", "kotlin.text.isNotEmpty", "any"), Conversion("kotlin.text.filter", "kotlin.text.isEmpty", "none"), - Conversion("kotlin.collections.map", "kotlin.collections.joinTo", "joinTo"), - Conversion("kotlin.collections.map", "kotlin.collections.joinToString", "joinToString"), + Conversion("kotlin.collections.map", "kotlin.collections.joinTo", "joinTo", enableSuspendFunctionCall = false), + Conversion("kotlin.collections.map", "kotlin.collections.joinToString", "joinToString", enableSuspendFunctionCall = false), Conversion("kotlin.collections.map", "kotlin.collections.filterNotNull", "mapNotNull"), Conversion("kotlin.collections.listOf", "kotlin.collections.filterNotNull", "listOfNotNull") diff --git a/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithSuspendFunctionCall.kt b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithSuspendFunctionCall.kt new file mode 100644 index 00000000000..2a65160b0db --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithSuspendFunctionCall.kt @@ -0,0 +1,8 @@ +// PROBLEM: none +// WITH_RUNTIME + +suspend fun mapString(input: String): String = "" + +suspend fun main() { + val x = listOf("1", "2", "3").map { mapString(it) }.joinToString() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithSuspendFunctionCall.kt b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithSuspendFunctionCall.kt new file mode 100644 index 00000000000..744759780a4 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithSuspendFunctionCall.kt @@ -0,0 +1,9 @@ +// PROBLEM: none +// WITH_RUNTIME + +suspend fun mapString(input: String): String = "" + +suspend fun main() { + val sb = StringBuilder() + val x = listOf("1", "2", "3").map { mapString(it) }.joinTo(sb) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt new file mode 100644 index 00000000000..c0ebb65b7d2 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +suspend fun mapString(input: String): String? = "" + +suspend fun main() { + val x = listOf("1", "2", "3").map { mapString(it) }.filterNotNull() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt.after b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt.after new file mode 100644 index 00000000000..de620caf5c2 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +suspend fun mapString(input: String): String? = "" + +suspend fun main() { + val x = listOf("1", "2", "3").mapNotNull { mapString(it) } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index d052704719d..2d94c951fc1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -1897,11 +1897,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithReferenceFake.kt"); } + @TestMetadata("joinToStringWithSuspendFunctionCall.kt") + public void testJoinToStringWithSuspendFunctionCall() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithSuspendFunctionCall.kt"); + } + @TestMetadata("joinToWithComment.kt") public void testJoinToWithComment() throws Exception { runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithComment.kt"); } + @TestMetadata("joinToWithSuspendFunctionCall.kt") + public void testJoinToWithSuspendFunctionCall() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToWithSuspendFunctionCall.kt"); + } + @TestMetadata("listOfNotNull.kt") public void testListOfNotNull() throws Exception { runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/listOfNotNull.kt"); @@ -1917,6 +1927,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNull.kt"); } + @TestMetadata("mapNotNullWithSuspendFunctionCall.kt") + public void testMapNotNullWithSuspendFunctionCall() throws Exception { + runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNullWithSuspendFunctionCall.kt"); + } + @TestMetadata("mapWithReturn.kt") public void testMapWithReturn() throws Exception { runTest("idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapWithReturn.kt");