Fix Can't rename implicit lambda parameter 'it' when caret is placed right after the last character
#KT-14401 Fixed
This commit is contained in:
committed by
Alexey Sedunov
parent
e3391175d9
commit
1bad04db50
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,17 +21,15 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
|
||||
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() {
|
||||
class RenameKotlinImplicitLambdaParameter : VariableInplaceRenameHandler() {
|
||||
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
||||
val nameExpression = PsiTreeUtil.findElementOfClassAtOffset(
|
||||
file, editor.caretModel.offset, KtNameReferenceExpression::class.java, false)
|
||||
val nameExpression = file.findElementForRename<KtNameReferenceExpression>(editor.caretModel.offset)
|
||||
|
||||
return nameExpression != null && isAutoCreatedItUsage(nameExpression)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.refactoring.rename.ResolvableCollisionUsageInfo
|
||||
import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
@@ -79,4 +81,9 @@ class LostDefaultValuesInOverridingFunctionUsageInfo(
|
||||
subParam.addRange(superParam.equalsToken, defaultValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : PsiElement> PsiFile.findElementForRename(offset: Int): T? {
|
||||
return PsiTreeUtil.findElementOfClassAtOffset(this, offset, T::class.java, false)
|
||||
?: PsiTreeUtil.findElementOfClassAtOffset(this, (offset - 1).coerceAtLeast(0), T::class.java, false)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun f() {
|
||||
val f: (Int) -> Int = { it<caret> + it }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun f() {
|
||||
val f: (Int) -> Int = { y -> y + y }
|
||||
}
|
||||
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaPa
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||
import com.intellij.codeInsight.template.TemplateManager
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
||||
override fun isRunInWriteAction(): Boolean = false
|
||||
@@ -50,19 +52,58 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
||||
}
|
||||
|
||||
fun testFunctionLiteralIt() {
|
||||
doTestImplicitLambdaParameter("y")
|
||||
}
|
||||
|
||||
fun testFunctionLiteralItEndCaret() {
|
||||
doTestImplicitLambdaParameter("y")
|
||||
}
|
||||
|
||||
fun testFunctionLiteralParenthesis() {
|
||||
doTestInplaceRename("y")
|
||||
}
|
||||
|
||||
fun testLocalFunction() {
|
||||
doTestInplaceRename("bar")
|
||||
}
|
||||
|
||||
fun testFunctionParameterNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testGlobalFunctionNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testTopLevelValNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testLabelFromFunction() {
|
||||
doTestInplaceRename("foo")
|
||||
}
|
||||
|
||||
fun testMultiDeclaration() {
|
||||
doTestInplaceRename("foo")
|
||||
}
|
||||
|
||||
fun testLocalVarShadowingMemberProperty() {
|
||||
doTestInplaceRename("name1")
|
||||
}
|
||||
|
||||
private fun doTestImplicitLambdaParameter(newName: String) {
|
||||
configureByFile(getTestName(false) + ".kt")
|
||||
val newName = "y"
|
||||
|
||||
// This code is copy-pasted from CodeInsightTestUtil.doInlineRename() and slightly modified.
|
||||
// Original method was not suitable because it expects renamed element to be reference to other or referrable
|
||||
|
||||
val file = LightPlatformCodeInsightTestCase.getFile()!!
|
||||
val editor = LightPlatformCodeInsightTestCase.getEditor()!!
|
||||
val element = file.findReferenceAt(editor.caretModel.offset)!!.element
|
||||
val file = getFile()!!
|
||||
val editor = getEditor()!!
|
||||
val element = file.findElementForRename<KtNameReferenceExpression>(editor.caretModel.offset)!!
|
||||
assertNotNull(element)
|
||||
|
||||
val dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.name, element!!,
|
||||
LightPlatformCodeInsightTestCase.getCurrentEditorDataContext())
|
||||
getCurrentEditorDataContext())
|
||||
val handler = RenameKotlinImplicitLambdaParameter()
|
||||
|
||||
assertTrue(handler.isRenaming(dataContext), "In-place rename not allowed for " + element)
|
||||
@@ -100,38 +141,6 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
||||
checkResultByFile(getTestName(false) + ".kt.after")
|
||||
}
|
||||
|
||||
fun testFunctionLiteralParenthesis() {
|
||||
doTestInplaceRename("y")
|
||||
}
|
||||
|
||||
fun testLocalFunction() {
|
||||
doTestInplaceRename("bar")
|
||||
}
|
||||
|
||||
fun testFunctionParameterNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testGlobalFunctionNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testTopLevelValNotInplace() {
|
||||
doTestInplaceRename(null)
|
||||
}
|
||||
|
||||
fun testLabelFromFunction() {
|
||||
doTestInplaceRename("foo")
|
||||
}
|
||||
|
||||
fun testMultiDeclaration() {
|
||||
doTestInplaceRename("foo")
|
||||
}
|
||||
|
||||
fun testLocalVarShadowingMemberProperty() {
|
||||
doTestInplaceRename("name1")
|
||||
}
|
||||
|
||||
private fun doTestInplaceRename(newName: String?) {
|
||||
configureByFile(getTestName(false) + ".kt")
|
||||
val element = TargetElementUtilBase.findTargetElement(
|
||||
|
||||
Reference in New Issue
Block a user