Refactored ReplaceItWithExplicitFunctionLiteralParamIntention

This commit is contained in:
Valentin Kipyatkov
2015-04-28 19:28:25 +03:00
parent c7937f181b
commit 01a8ff0860
4 changed files with 29 additions and 48 deletions
@@ -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
@@ -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<JetSimpleNameExpression>()!!
public class ReplaceItWithExplicitFunctionLiteralParamIntention() : JetSelfTargetingOffsetIndependentIntention<JetSimpleNameExpression>(
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<JetSimpleNameExpression>()
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
}
}
}
@@ -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()
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]
}
@@ -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<JetSimpleNameExpression>(), false)
return simpleNameExpression != null
&& ReplaceItWithExplicitFunctionLiteralParamIntention.isAutoCreatedIt(simpleNameExpression)
return simpleNameExpression != null && isAutoCreatedItUsage(simpleNameExpression)
}
override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {