diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index b573a15f644..79e33973571 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -257,6 +257,7 @@
+
diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt
index c105eb2b637..27879050e42 100644
--- a/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt
+++ b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt
@@ -56,14 +56,7 @@ public class ReplaceItWithExplicitFunctionLiteralParamIntention() : PsiElementBa
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
val simpleNameExpression = PsiTreeUtil.getParentOfType(element, javaClass())
- if (simpleNameExpression == null || simpleNameExpression.getReferencedName() != "it") {
- return false
- }
-
- val bindingContext = AnalyzerFacadeWithCache.getContextForElement(simpleNameExpression)
- val reference = simpleNameExpression.getReference() as JetReference?
- val simpleNameTarget = reference?.resolveToDescriptors()?.firstOrNull() as? ValueParameterDescriptor?
- if (simpleNameTarget == null || bindingContext.get(BindingContext.AUTO_CREATED_IT, simpleNameTarget) != true) {
+ if (simpleNameExpression == null || !isAutoCreatedIt(simpleNameExpression)) {
return false
}
@@ -74,4 +67,21 @@ public class ReplaceItWithExplicitFunctionLiteralParamIntention() : PsiElementBa
override fun getFamilyName(): String {
return JetBundle.message("replace.it.with.explicit.function.literal.param.family")
}
+
+ class object {
+ fun isAutoCreatedIt(simpleNameExpression: JetSimpleNameExpression): Boolean {
+ if (simpleNameExpression.getReferencedName() != "it") {
+ return false
+ }
+
+ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(simpleNameExpression)
+ val reference = simpleNameExpression.getReference() as JetReference?
+ val simpleNameTarget = reference?.resolveToDescriptors()?.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/jet/plugin/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt
new file mode 100644
index 00000000000..a40ad97d52e
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.refactoring.rename
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
+import com.intellij.openapi.actionSystem.DataContext
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.editor.Editor
+import com.intellij.psi.PsiFile
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.jet.plugin.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
+import com.intellij.openapi.command.CommandProcessor
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
+
+public class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() {
+ override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
+ val simpleNameExpression = PsiTreeUtil.findElementOfClassAtOffset(
+ file, editor.getCaretModel().getOffset(), javaClass(), false)
+
+ return simpleNameExpression != null
+ && ReplaceItWithExplicitFunctionLiteralParamIntention.isAutoCreatedIt(simpleNameExpression)
+ }
+
+ override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {
+ val intention = ReplaceItWithExplicitFunctionLiteralParamIntention()
+ CommandProcessor.getInstance().executeCommand(
+ project,
+ { ApplicationManager.getApplication()!!.runWriteAction(Runnable {
+ intention.invoke(project, editor, file)
+ }) },
+ "Convert 'it' to explicit lambda parameter",
+ ""
+ )
+ }
+
+ override fun invoke(project: Project, elements: Array, dataContext: DataContext?) {
+ // Do nothing: this method is called not from editor
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt b/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt
new file mode 100644
index 00000000000..7f48570e510
--- /dev/null
+++ b/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt
@@ -0,0 +1,3 @@
+fun f() {
+ val f: (Int) -> Int = { it + it }
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt.after b/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt.after
new file mode 100644
index 00000000000..9dab32c0735
--- /dev/null
+++ b/idea/testData/refactoring/rename/inplace/FunctionLiteralIt.kt.after
@@ -0,0 +1,3 @@
+fun f() {
+ val f: (Int) -> Int = { y -> y + y }
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt b/idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt
index 068f2445530..9d154b13531 100644
--- a/idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt
+++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt
@@ -30,8 +30,23 @@ import org.jetbrains.jet.plugin.PluginTestCaseBase
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
+import com.intellij.refactoring.rename.RenameHandler
+import org.jetbrains.jet.plugin.refactoring.rename.RenameKotlinImplicitLambdaParameter
+import com.intellij.openapi.project.Project
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl
+import com.intellij.codeInsight.template.TemplateManager
+import com.intellij.refactoring.rename.inplace.InplaceRefactoring
+import com.intellij.injected.editor.EditorWindow
+import com.intellij.codeInsight.template.impl.TemplateState
+import com.intellij.openapi.util.TextRange
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.command.WriteCommandAction
+
+public class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
+ {
+ System.setProperty("idea.platform.prefix", "Idea")
+ }
-public class InplaceRenameTest : LightCodeInsightTestCase() {
override fun isRunInWriteAction(): Boolean = false
override fun getTestDataPath(): String = PluginTestCaseBase.getTestDataPathBase() + "/refactoring/rename/inplace/"
@@ -51,6 +66,59 @@ public class InplaceRenameTest : LightCodeInsightTestCase() {
doTestInplaceRename("y")
}
+ public fun testFunctionLiteralIt() {
+ 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.getCaretModel().getOffset())!!.getElement()
+ assertNotNull(element)
+
+ val dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.getName(), element!!,
+ LightPlatformCodeInsightTestCase.getCurrentEditorDataContext())
+ val handler = RenameKotlinImplicitLambdaParameter()
+
+ assertTrue(handler.isRenaming(dataContext), "In-place rename not allowed for " + element)
+
+ val project = editor.getProject()!!
+ val templateManager = TemplateManager.getInstance(project) as TemplateManagerImpl
+ try {
+ templateManager.setTemplateTesting(true)
+
+ object : WriteCommandAction.Simple(project) {
+ throws(javaClass())
+ override fun run() {
+ handler.invoke(project, editor, file, dataContext)
+ }
+ }.execute()
+
+ var state = TemplateManagerImpl.getTemplateState(editor)
+ assert(state != null)
+ val range = state!!.getCurrentVariableRange()
+ assert(range != null)
+ object : WriteCommandAction.Simple(project) {
+ throws(javaClass())
+ override fun run() {
+ editor.getDocument().replaceString(range!!.getStartOffset(), range!!.getEndOffset(), newName)
+ }
+ }.execute().throwException()
+
+ state = TemplateManagerImpl.getTemplateState(editor)
+ assert(state != null)
+ state!!.gotoEnd(false)
+ }
+ finally {
+ templateManager.setTemplateTesting(false)
+ }
+
+
+ checkResultByFile(getTestName(false) + ".kt.after")
+ }
+
public fun testFunctionLiteralParenthesis() {
doTestInplaceRename("y")
}