SimplifyCallChainFix: take Conversion instead of raw text, polish a bit

This commit is contained in:
Mikhail Glukhikh
2018-11-28 19:38:39 +03:00
parent b6630699aa
commit 9f5255da02
7 changed files with 32 additions and 28 deletions
@@ -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 {
@@ -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()
@@ -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,
@@ -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)
})
@@ -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)
})
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// FIX: Merge call chain to 'withContext(Default)'
// FIX: Merge call chain to 'withContext'
package kotlinx.coroutines
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// FIX: Merge call chain to 'withContext(Default)'
// FIX: Merge call chain to 'withContext'
package kotlinx.coroutines