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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
|
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
|
||||||
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
|
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
|
||||||
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
|
||||||
class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() {
|
class RenameKotlinImplicitLambdaParameter : VariableInplaceRenameHandler() {
|
||||||
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
||||||
val nameExpression = PsiTreeUtil.findElementOfClassAtOffset(
|
val nameExpression = file.findElementForRename<KtNameReferenceExpression>(editor.caretModel.offset)
|
||||||
file, editor.caretModel.offset, KtNameReferenceExpression::class.java, false)
|
|
||||||
|
|
||||||
return nameExpression != null && isAutoCreatedItUsage(nameExpression)
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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
|
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
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.ResolvableCollisionUsageInfo
|
||||||
import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||||
@@ -79,4 +81,9 @@ class LostDefaultValuesInOverridingFunctionUsageInfo(
|
|||||||
subParam.addRange(superParam.equalsToken, defaultValue)
|
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.impl.TemplateManagerImpl
|
||||||
import com.intellij.codeInsight.template.TemplateManager
|
import com.intellij.codeInsight.template.TemplateManager
|
||||||
import com.intellij.openapi.command.WriteCommandAction
|
import com.intellij.openapi.command.WriteCommandAction
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
|
||||||
class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
||||||
override fun isRunInWriteAction(): Boolean = false
|
override fun isRunInWriteAction(): Boolean = false
|
||||||
@@ -50,19 +52,58 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testFunctionLiteralIt() {
|
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")
|
configureByFile(getTestName(false) + ".kt")
|
||||||
val newName = "y"
|
|
||||||
|
|
||||||
// This code is copy-pasted from CodeInsightTestUtil.doInlineRename() and slightly modified.
|
// 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
|
// Original method was not suitable because it expects renamed element to be reference to other or referrable
|
||||||
|
|
||||||
val file = LightPlatformCodeInsightTestCase.getFile()!!
|
val file = getFile()!!
|
||||||
val editor = LightPlatformCodeInsightTestCase.getEditor()!!
|
val editor = getEditor()!!
|
||||||
val element = file.findReferenceAt(editor.caretModel.offset)!!.element
|
val element = file.findElementForRename<KtNameReferenceExpression>(editor.caretModel.offset)!!
|
||||||
assertNotNull(element)
|
assertNotNull(element)
|
||||||
|
|
||||||
val dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.name, element!!,
|
val dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.name, element!!,
|
||||||
LightPlatformCodeInsightTestCase.getCurrentEditorDataContext())
|
getCurrentEditorDataContext())
|
||||||
val handler = RenameKotlinImplicitLambdaParameter()
|
val handler = RenameKotlinImplicitLambdaParameter()
|
||||||
|
|
||||||
assertTrue(handler.isRenaming(dataContext), "In-place rename not allowed for " + element)
|
assertTrue(handler.isRenaming(dataContext), "In-place rename not allowed for " + element)
|
||||||
@@ -100,38 +141,6 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
|||||||
checkResultByFile(getTestName(false) + ".kt.after")
|
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?) {
|
private fun doTestInplaceRename(newName: String?) {
|
||||||
configureByFile(getTestName(false) + ".kt")
|
configureByFile(getTestName(false) + ".kt")
|
||||||
val element = TargetElementUtilBase.findTargetElement(
|
val element = TargetElementUtilBase.findTargetElement(
|
||||||
|
|||||||
Reference in New Issue
Block a user