From 5a1a35bb352291bd27c5d15ef0a1040ec6e28b5d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 20 Dec 2017 21:06:31 +0300 Subject: [PATCH] Refactoring: "replace put with assignment" is now applicability-based --- .../ReplacePutWithAssignmentInspection.kt | 90 ++++++++----------- .../kotlin/idea/j2k/J2kPostProcessings.kt | 17 +--- 2 files changed, 40 insertions(+), 67 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt index 11d1b985ff3..c5b45afb77f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt @@ -16,73 +16,61 @@ package org.jetbrains.kotlin.idea.inspections -import com.intellij.codeInspection.LocalQuickFix -import com.intellij.codeInspection.ProblemDescriptor -import com.intellij.codeInspection.ProblemHighlightType -import com.intellij.codeInspection.ProblemsHolder +import com.intellij.codeInspection.* +import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElementVisitor +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.callExpression import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf -class ReplacePutWithAssignmentInspection : AbstractKotlinInspection() { - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { - return object : KtVisitorVoid() { - override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) { - super.visitDotQualifiedExpression(expression) - if (isActiveFor(expression)) { - holder.registerProblem( - expression.callExpression!!.calleeExpression!!, - "map.put() can be converted to assignment", - ProblemHighlightType.WEAK_WARNING, - ReplacePutWithAssignmentQuickfix() - ) +class ReplacePutWithAssignmentInspection : AbstractApplicabilityBasedInspection() { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): KtVisitorVoid = + object : KtVisitorVoid() { + override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) { + super.visitDotQualifiedExpression(expression) + visitTargetElement(expression, holder, isOnTheFly) } } - } + + override fun isApplicable(element: KtDotQualifiedExpression): Boolean { + val callExpression = element.callExpression + if (callExpression?.valueArguments?.size != 2) return false + + val calleeExpression = callExpression.calleeExpression as? KtNameReferenceExpression ?: return false + if (calleeExpression.getReferencedName() !in compatibleNames) return false + + val context = element.analyze() + if (element.isUsedAsExpression(context)) return false + val resolvedCall = element.getResolvedCall(context) + val receiverType = resolvedCall?.getExplicitReceiverValue()?.type ?: return false + val receiverClass = receiverType.constructor.declarationDescriptor as? ClassDescriptor ?: return false + return receiverClass.isSubclassOf(DefaultBuiltIns.Instance.mutableMap) } + override fun applyTo(element: PsiElement, project: Project, editor: Editor?) { + val expression = element.getParentOfType(strict = false) ?: return + val valueArguments = expression.callExpression?.valueArguments ?: return + expression.replace(KtPsiFactory(expression).createExpressionByPattern("$0[$1] = $2", + expression.receiverExpression, + valueArguments[0]?.getArgumentExpression() ?: return, + valueArguments[1]?.getArgumentExpression() ?: return)) + } + + override fun inspectionTarget(element: KtDotQualifiedExpression) = element.callExpression?.calleeExpression ?: element + + override fun inspectionText(element: KtDotQualifiedExpression): String = "map.put() can be converted to assignment" + + override val defaultFixText = "Convert put to assignment" + companion object { private val compatibleNames = setOf("put") - - fun isActiveFor(expression: KtDotQualifiedExpression): Boolean { - val callExpression = expression.callExpression - if (callExpression?.valueArguments?.size != 2) return false - - val calleeExpression = callExpression.calleeExpression as? KtNameReferenceExpression ?: return false - if (calleeExpression.getReferencedName() !in compatibleNames) return false - - val context = expression.analyze() - if (expression.isUsedAsExpression(context)) return false - val resolvedCall = expression.getResolvedCall(context) - val receiverType = resolvedCall?.getExplicitReceiverValue()?.type ?: return false - val receiverClass = receiverType.constructor.declarationDescriptor as? ClassDescriptor ?: return false - return receiverClass.isSubclassOf(DefaultBuiltIns.Instance.mutableMap) - } - - fun simplify(expression: KtDotQualifiedExpression) { - val valueArguments = expression.callExpression?.valueArguments ?: return - expression.replace(KtPsiFactory(expression).createExpressionByPattern("$0[$1] = $2", - expression.receiverExpression, - valueArguments[0]?.getArgumentExpression() ?: return, - valueArguments[1]?.getArgumentExpression() ?: return)) - } - } - - class ReplacePutWithAssignmentQuickfix : LocalQuickFix { - override fun getName() = "Convert put to assignment" - - override fun getFamilyName() = name - - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - simplify(descriptor.psiElement.parent.parent as? KtDotQualifiedExpression ?: return) - } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt index 24120049b70..e8f836a513e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt @@ -78,7 +78,7 @@ object J2KPostProcessingRegistrar { _processings.add(UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing()) _processings.add(RemoveRedundantSamAdaptersProcessing()) _processings.add(RemoveRedundantCastToNullableProcessing()) - _processings.add(ReplacePutWithAssignmentProcessing()) + registerInspectionBasedProcessing(ReplacePutWithAssignmentInspection()) _processings.add(UseExpressionBodyProcessing()) _processings.add(UnnecessaryVariableProcessing()) @@ -300,21 +300,6 @@ object J2KPostProcessingRegistrar { } } - private class ReplacePutWithAssignmentProcessing : J2kPostProcessing { - override val writeActionNeeded = true - - override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { - if (element !is KtDotQualifiedExpression) return null - if (!ReplacePutWithAssignmentInspection.isActiveFor(element)) return null - - return { - if (ReplacePutWithAssignmentInspection.isActiveFor(element)) { - ReplacePutWithAssignmentInspection.simplify(element) - } - } - } - } - private class UseExpressionBodyProcessing : J2kPostProcessing { override val writeActionNeeded = true