Redundant async: extract generateConversion, integrate arguments inside
This commit is contained in:
+5
-1
@@ -63,7 +63,7 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() {
|
|||||||
constructor(first: KtExpression, second: KtExpression) : this(first.text, second.text)
|
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 != '.' }
|
private fun String.convertToShort() = takeLastWhile { it != '.' }
|
||||||
|
|
||||||
val id: ConversionId get() = ConversionId(firstName, secondName)
|
val id: ConversionId get() = ConversionId(firstName, secondName)
|
||||||
@@ -71,6 +71,10 @@ abstract class AbstractCallChainChecker : AbstractKotlinInspection() {
|
|||||||
val firstName = firstFqName.convertToShort()
|
val firstName = firstFqName.convertToShort()
|
||||||
|
|
||||||
val secondName = secondFqName.convertToShort()
|
val secondName = secondFqName.convertToShort()
|
||||||
|
|
||||||
|
fun withArgumentList(argumentList: String) = Conversion(firstFqName, secondFqName, replacement, argumentList)
|
||||||
|
|
||||||
|
val fullReplacement: String get() = replacement + (argumentList ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+34
-27
@@ -15,43 +15,50 @@ import org.jetbrains.kotlin.psi.qualifiedExpressionVisitor
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||||
|
|
||||||
class RedundantAsyncInspection : AbstractCallChainChecker() {
|
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, _, _ ->
|
private fun generateConversion(expression: KtQualifiedExpression): Conversion? {
|
||||||
for ((parameterDescriptor, valueArgument) in firstResolvedCall.valueArguments) {
|
var defaultContext: Boolean? = null
|
||||||
val default = valueArgument is DefaultValueArgument
|
var defaultStart: Boolean? = null
|
||||||
when (parameterDescriptor.name.asString()) {
|
// Temporary forbid cases with explicit scope
|
||||||
"context" -> defaultContext = default
|
if (expression.receiverExpression is KtQualifiedExpression) return null
|
||||||
"start" -> defaultStart = default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
} ?: return
|
|
||||||
defaultContext ?: return
|
|
||||||
defaultStart ?: return
|
|
||||||
if (defaultContext!! && !defaultStart!!) return
|
|
||||||
|
|
||||||
var replacement = conversion.replacement
|
var conversion = findQualifiedConversion(expression, conversionGroups) check@{ _, firstResolvedCall, _, _ ->
|
||||||
if (defaultContext!! && defaultStart!!) {
|
for ((parameterDescriptor, valueArgument) in firstResolvedCall.valueArguments) {
|
||||||
if (conversion === conversions[0]) {
|
val default = valueArgument is DefaultValueArgument
|
||||||
replacement += "($defaultAsyncArgument)"
|
when (parameterDescriptor.name.asString()) {
|
||||||
} else {
|
"context" -> defaultContext = default
|
||||||
replacement += "($defaultAsyncArgumentExperimental)"
|
"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(
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
expression,
|
expression,
|
||||||
expression.firstCalleeExpression()!!.textRange.shiftRight(-expression.startOffset),
|
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,
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
isOnTheFly,
|
isOnTheFly,
|
||||||
SimplifyCallChainFix(replacement)
|
SimplifyCallChainFix(fullReplacement)
|
||||||
)
|
)
|
||||||
holder.registerProblem(descriptor)
|
holder.registerProblem(descriptor)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user