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 4f85d99a9a8..c7c2038e13e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull abstract class AbstractCallChainChecker : AbstractKotlinInspection() { @@ -63,18 +62,21 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() { constructor(first: KtExpression, second: KtExpression) : this(first.text, second.text) } - data class Conversion(val firstFqName: String, val secondFqName: String, val replacement: String, val argumentList: String? = null) { + data class Conversion( + val firstFqName: String, + val secondFqName: String, + val replacement: String, + val additionalArgument: String? = null + ) { private fun String.convertToShort() = takeLastWhile { it != '.' } val id: ConversionId get() = ConversionId(firstName, secondName) - val firstName = firstFqName.convertToShort() + private val firstName = firstFqName.convertToShort() - val secondName = secondFqName.convertToShort() + private val secondName = secondFqName.convertToShort() - fun withArgumentList(argumentList: String) = Conversion(firstFqName, secondFqName, replacement, argumentList) - - val fullReplacement: String get() = replacement + (argumentList ?: "") + fun withArgument(argument: String) = Conversion(firstFqName, secondFqName, replacement, argument) } companion object { 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 d89b64bbfcd..1a12e4bbb54 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallChainInspection.kt @@ -45,7 +45,7 @@ class SimplifiableCallChainInspection : AbstractCallChainChecker() { "Call chain on collection type may be simplified", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - SimplifyCallChainFix(replacement) { callExpression -> + SimplifyCallChainFix(conversion) { callExpression -> val lastArgumentName = if (replacement.startsWith("joinTo")) Name.identifier("transform") else null if (lastArgumentName != null) { val lastArgument = callExpression.valueArgumentList?.arguments?.singleOrNull() diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt index 488fed96a91..68360dc8ca7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifyCallChainFix.kt @@ -25,13 +25,11 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange class SimplifyCallChainFix( - private val newCallText: String, + private val conversion: AbstractCallChainChecker.Conversion, private val removeReceiverOfFirstCall: Boolean = false, private val modifyArguments: KtPsiFactory.(KtCallExpression) -> Unit = {} ) : LocalQuickFix { - private val shortenedText = newCallText.split("(").joinToString(separator = "(") { - it.substringAfterLast(".") - } + private val shortenedText = conversion.replacement.substringAfterLast(".") override fun getName() = "Merge call chain to '$shortenedText'" @@ -67,16 +65,21 @@ class SimplifyCallChainFix( secondCallArgumentList.takeIf { it?.arguments?.isNotEmpty() == true }, firstCallArgumentList.takeIf { it?.arguments?.isNotEmpty() == true } ).let { - if (it.isEmpty()) "" - else it.joinToString( - separator = ", ", - prefix = "(", - postfix = ")" - ) { callArgumentList -> - callArgumentList.getTextInsideParentheses() + val additionalArgument = conversion.additionalArgument + when { + it.isNotEmpty() -> it.joinToString( + separator = ", ", + prefix = "(", + postfix = ")" + ) { callArgumentList -> + callArgumentList.getTextInsideParentheses() + } + additionalArgument != null -> "($additionalArgument)" + else -> "" } } + val newCallText = conversion.replacement val newQualifiedExpression = if (lambdaExpression != null) factory.createExpressionByPattern( "$0$1$2 $3 $4", receiverExpressionOrEmptyString, diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt index 8a2bf786024..24324db46e1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt @@ -51,11 +51,11 @@ class RedundantAsyncInspection : AbstractCallChainChecker() { } if (defaultContext!! && defaultStart!!) { - conversion = conversion.withArgumentList( + conversion = conversion.withArgument( if (conversion === conversions[0]) { - "($DEFAULT_ASYNC_ARGUMENT)" + DEFAULT_ASYNC_ARGUMENT } else { - "($DEFAULT_ASYNC_ARGUMENT_EXPERIMENTAL)" + DEFAULT_ASYNC_ARGUMENT_EXPERIMENTAL } ) } @@ -65,14 +65,13 @@ class RedundantAsyncInspection : AbstractCallChainChecker() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = qualifiedExpressionVisitor(fun(expression) { val conversion = generateConversion(expression) ?: return - val fullReplacement = conversion.fullReplacement val descriptor = holder.manager.createProblemDescriptor( expression, expression.firstCalleeExpression()!!.textRange.shiftRight(-expression.startOffset), - "Redundant 'async' call may be reduced to '$fullReplacement'", + "Redundant 'async' call may be reduced to '${conversion.replacement}'", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - SimplifyCallChainFix(fullReplacement, removeReceiverOfFirstCall = true) + SimplifyCallChainFix(conversion, removeReceiverOfFirstCall = true) ) holder.registerProblem(descriptor) }) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantRunCatchingInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantRunCatchingInspection.kt index 5c977846181..fa5d7a59604 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantRunCatchingInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantRunCatchingInspection.kt @@ -24,7 +24,7 @@ class RedundantRunCatchingInspection : AbstractCallChainChecker() { "Redundant 'runCatching' call may be reduced to '$replacement'", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - SimplifyCallChainFix(replacement) + SimplifyCallChainFix(conversion) ) holder.registerProblem(descriptor) }) diff --git a/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt b/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt index 2bdfe30acda..93d37878616 100644 --- a/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt +++ b/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Merge call chain to 'withContext(Default)' +// FIX: Merge call chain to 'withContext' package kotlinx.coroutines diff --git a/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt.after b/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt.after index e096e6b1311..8e7dfd341fb 100644 --- a/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt.after +++ b/idea/testData/inspectionsLocal/coroutines/redundantAsync/simplest.kt.after @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Merge call chain to 'withContext(Default)' +// FIX: Merge call chain to 'withContext' package kotlinx.coroutines