From 01a8ff086047b49a3ebb148457da4fa30f0763b7 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 28 Apr 2015 19:28:25 +0300 Subject: [PATCH] Refactored ReplaceItWithExplicitFunctionLiteralParamIntention --- .../kotlin/idea/JetBundle.properties | 2 - ...thExplicitFunctionLiteralParamIntention.kt | 59 +++++-------------- .../jetbrains/kotlin/idea/intentions/Utils.kt | 12 +++- .../RenameKotlinImplicitLambdaParameter.kt | 4 +- 4 files changed, 29 insertions(+), 48 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties index a63e3c212ac..6c8a8c4d3c1 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties @@ -296,8 +296,6 @@ replace.with.infix.function.call.intention=Replace with infix function call replace.with.infix.function.call.intention.family=Replace with Infix Function Call replace.with.infix.function.call.intention.error.resolution.failed=The element cannot be resolved replace.with.infix.function.call.intention.error.package.call=Cannot be applied with a package as the receiver -replace.it.with.explicit.function.literal.param=Replace 'it' with explicit parameter -replace.it.with.explicit.function.literal.param.family=Replace 'it' with Explicit Parameter split.if=Split into 2 if's split.if.family=Split If replace.with.operator.assign.intention=Replace with an operator-assign expression diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt index 544c42bae7b..2341093c3d1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt @@ -35,54 +35,27 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -public class ReplaceItWithExplicitFunctionLiteralParamIntention() : PsiElementBaseIntentionAction() { - override fun invoke(project: Project, editor: Editor, element: PsiElement) { - val simpleNameExpression = element.getStrictParentOfType()!! +public class ReplaceItWithExplicitFunctionLiteralParamIntention() : JetSelfTargetingOffsetIndependentIntention( + javaClass(), "Replace 'it' with explicit parameter" +) { + override fun isApplicableTo(element: JetSimpleNameExpression) + = isAutoCreatedItUsage(element) - val simpleNameReference = simpleNameExpression.getReference() as JetReference? - val target = simpleNameReference?.resolveToDescriptors(simpleNameExpression.analyze(BodyResolveMode.PARTIAL))?.first()!! + override fun applyTo(element: JetSimpleNameExpression, editor: Editor) { + val reference = element.getReference() as JetReference + val target = reference.resolveToDescriptors(element.analyze()).first() - val funcExpr = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as JetFunctionLiteral + val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as JetFunctionLiteral - val newExpr = JetPsiFactory(simpleNameExpression).createExpression("{ it -> 42 }") as JetFunctionLiteralExpression - funcExpr.addRangeAfter(newExpr.getFunctionLiteral().getValueParameterList(), - newExpr.getFunctionLiteral().getArrowNode()!!.getPsi(), - funcExpr.getLBrace()) - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()) + val newExpr = JetPsiFactory(element).createExpression("{ it -> }") as JetFunctionLiteralExpression + functionLiteral.addRangeAfter( + newExpr.getFunctionLiteral().getValueParameterList(), + newExpr.getFunctionLiteral().getArrowNode()!!.getPsi(), + functionLiteral.getLBrace()) + PsiDocumentManager.getInstance(element.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument()) - val paramToRename = funcExpr.getValueParameters().first() + val paramToRename = functionLiteral.getValueParameters().single() editor.getCaretModel().moveToOffset(paramToRename.getTextOffset()) VariableInplaceRenameHandler().doRename(paramToRename, editor, null) } - - override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean { - val simpleNameExpression = element.getStrictParentOfType() - if (simpleNameExpression == null || !isAutoCreatedIt(simpleNameExpression)) { - return false - } - - setText(JetBundle.message("replace.it.with.explicit.function.literal.param")) - return true - } - - override fun getFamilyName(): String { - return JetBundle.message("replace.it.with.explicit.function.literal.param.family") - } - - companion object { - fun isAutoCreatedIt(simpleNameExpression: JetSimpleNameExpression): Boolean { - if (simpleNameExpression.getReferencedName() != "it") { - return false - } - - val bindingContext = simpleNameExpression.analyze(BodyResolveMode.PARTIAL) - val reference = simpleNameExpression.getReference() as JetReference? - val simpleNameTarget = reference?.resolveToDescriptors(bindingContext)?.firstOrNull() as? ValueParameterDescriptor? - if (simpleNameTarget == null || bindingContext.get(BindingContext.AUTO_CREATED_IT, simpleNameTarget) != true) { - return false - } - - return true - } - } } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt index d598677dc6d..f7d794a1596 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt @@ -19,7 +19,9 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.JetNodeTypes import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.references.JetReference import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.ShortenReferences import org.jetbrains.kotlin.psi.* @@ -70,4 +72,12 @@ fun JetContainerNode.description(): String? { return null } -fun TextRange.containsInside(offset: Int) = getStartOffset() < offset && offset < getEndOffset() \ No newline at end of file +fun TextRange.containsInside(offset: Int) = getStartOffset() < offset && offset < getEndOffset() + +fun isAutoCreatedItUsage(expression: JetSimpleNameExpression): Boolean { + if (expression.getReferencedName() != "it") return false + val context = expression.analyze() + val reference = expression.getReference() as JetReference? + val target = reference?.resolveToDescriptors(context)?.firstOrNull() as? ValueParameterDescriptor? ?: return false + return context[BindingContext.AUTO_CREATED_IT, target] +} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt index a213a59e585..36b58675a2c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteral import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.application.ApplicationManager import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler +import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage import org.jetbrains.kotlin.idea.util.application.executeWriteCommand public class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() { @@ -34,8 +35,7 @@ public class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() val simpleNameExpression = PsiTreeUtil.findElementOfClassAtOffset( file, editor.getCaretModel().getOffset(), javaClass(), false) - return simpleNameExpression != null - && ReplaceItWithExplicitFunctionLiteralParamIntention.isAutoCreatedIt(simpleNameExpression) + return simpleNameExpression != null && isAutoCreatedItUsage(simpleNameExpression) } override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {