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 da97c79fba2..4f85d99a9a8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/AbstractCallChainChecker.kt @@ -63,7 +63,7 @@ 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) { + data class Conversion(val firstFqName: String, val secondFqName: String, val replacement: String, val argumentList: String? = null) { private fun String.convertToShort() = takeLastWhile { it != '.' } val id: ConversionId get() = ConversionId(firstName, secondName) @@ -71,6 +71,10 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() { val firstName = firstFqName.convertToShort() val secondName = secondFqName.convertToShort() + + fun withArgumentList(argumentList: String) = Conversion(firstFqName, secondFqName, replacement, argumentList) + + val fullReplacement: String get() = replacement + (argumentList ?: "") } companion object { 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 14d70bf331c..60ccccee38d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/coroutines/RedundantAsyncInspection.kt @@ -15,43 +15,50 @@ import org.jetbrains.kotlin.psi.qualifiedExpressionVisitor import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument class RedundantAsyncInspection : AbstractCallChainChecker() { - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = - qualifiedExpressionVisitor(fun(expression) { - var defaultContext: Boolean? = null - var defaultStart: Boolean? = null - // Temporary forbid cases with explicit scope - if (expression.receiverExpression is KtQualifiedExpression) return - val conversion = findQualifiedConversion(expression, conversionGroups) check@{ _, firstResolvedCall, _, _ -> - for ((parameterDescriptor, valueArgument) in firstResolvedCall.valueArguments) { - val default = valueArgument is DefaultValueArgument - when (parameterDescriptor.name.asString()) { - "context" -> defaultContext = default - "start" -> defaultStart = default - } - } - true - } ?: return - defaultContext ?: return - defaultStart ?: return - if (defaultContext!! && !defaultStart!!) return + private fun generateConversion(expression: KtQualifiedExpression): Conversion? { + var defaultContext: Boolean? = null + var defaultStart: Boolean? = null + // Temporary forbid cases with explicit scope + if (expression.receiverExpression is KtQualifiedExpression) return null - var replacement = conversion.replacement - if (defaultContext!! && defaultStart!!) { - if (conversion === conversions[0]) { - replacement += "($defaultAsyncArgument)" - } else { - replacement += "($defaultAsyncArgumentExperimental)" + var conversion = findQualifiedConversion(expression, conversionGroups) check@{ _, firstResolvedCall, _, _ -> + for ((parameterDescriptor, valueArgument) in firstResolvedCall.valueArguments) { + val default = valueArgument is DefaultValueArgument + when (parameterDescriptor.name.asString()) { + "context" -> defaultContext = default + "start" -> defaultStart = default } } + true + } ?: return null + defaultContext ?: return null + defaultStart ?: return null + if (defaultContext!! && !defaultStart!!) return null + if (defaultContext!! && defaultStart!!) { + conversion = conversion.withArgumentList( + if (conversion === conversions[0]) { + "($defaultAsyncArgument)" + } else { + "($defaultAsyncArgumentExperimental)" + } + ) + } + return conversion + } + + 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 '$replacement'", + "Redundant 'async' call may be reduced to '$fullReplacement'", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - SimplifyCallChainFix(replacement) + SimplifyCallChainFix(fullReplacement) ) holder.registerProblem(descriptor) })