From 90ad65bff83c1829134b91b0e155d14a8f4e02e8 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 23 Dec 2013 21:18:19 +0400 Subject: [PATCH] Made rename refactoring inplace for loop, catch and function literal parameters. #KT-1296 fixed --- .../jetbrains/jet/lang/psi/JetPsiUtil.java | 8 +- .../JetRefactoringSupportProvider.java | 15 ++- .../refactoring/rename/inplace/ForLoop.kt | 5 + .../rename/inplace/ForLoop.kt.after | 5 + .../rename/inplace/FunctionLiteral.kt | 3 + .../rename/inplace/FunctionLiteral.kt.after | 3 + .../inplace/FunctionLiteralParenthesis.kt | 3 + .../FunctionLiteralParenthesis.kt.after | 3 + .../inplace/FunctionParameterNotInplace.kt | 2 + .../inplace/GlobalFunctionNotInplace.kt | 8 ++ .../rename/inplace/LocalFunction.kt | 7 ++ .../rename/inplace/LocalFunction.kt.after | 7 ++ .../refactoring/rename/inplace/LocalVal.kt | 4 + .../rename/inplace/LocalVal.kt.after | 4 + .../rename/inplace/TopLevelValNotInplace.kt | 5 + .../refactoring/rename/inplace/TryCatch.kt | 7 ++ .../rename/inplace/TryCatch.kt.after | 7 ++ .../plugin/refactoring/InplaceRenameTest.kt | 96 +++++++++++++++++++ 18 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 idea/testData/refactoring/rename/inplace/ForLoop.kt create mode 100644 idea/testData/refactoring/rename/inplace/ForLoop.kt.after create mode 100644 idea/testData/refactoring/rename/inplace/FunctionLiteral.kt create mode 100644 idea/testData/refactoring/rename/inplace/FunctionLiteral.kt.after create mode 100644 idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt create mode 100644 idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt.after create mode 100644 idea/testData/refactoring/rename/inplace/FunctionParameterNotInplace.kt create mode 100644 idea/testData/refactoring/rename/inplace/GlobalFunctionNotInplace.kt create mode 100644 idea/testData/refactoring/rename/inplace/LocalFunction.kt create mode 100644 idea/testData/refactoring/rename/inplace/LocalFunction.kt.after create mode 100644 idea/testData/refactoring/rename/inplace/LocalVal.kt create mode 100644 idea/testData/refactoring/rename/inplace/LocalVal.kt.after create mode 100644 idea/testData/refactoring/rename/inplace/TopLevelValNotInplace.kt create mode 100644 idea/testData/refactoring/rename/inplace/TryCatch.kt create mode 100644 idea/testData/refactoring/rename/inplace/TryCatch.kt.after create mode 100644 idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 2849c79a279..843719a2c92 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -1006,9 +1006,15 @@ public class JetPsiUtil { @Nullable public static JetElement getEnclosingElementForLocalDeclaration(@Nullable JetNamedDeclaration declaration) { - if (declaration instanceof JetTypeParameter || declaration instanceof JetParameter) { + if (declaration instanceof JetTypeParameter) { declaration = PsiTreeUtil.getParentOfType(declaration, JetNamedDeclaration.class); } + else if (declaration instanceof JetParameter) { + PsiElement parent = declaration.getParent(); + if (parent != null && parent.getParent() instanceof JetNamedFunction) { + declaration = (JetNamedFunction) parent.getParent(); + } + } //noinspection unchecked JetElement container = PsiTreeUtil.getParentOfType( diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java index d55c7b0be7d..735e46d3f57 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringSupportProvider.java @@ -20,6 +20,7 @@ import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.psi.PsiElement; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeSignatureHandler; @@ -28,7 +29,7 @@ import org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinSafeDeleteProcessor public class JetRefactoringSupportProvider extends RefactoringSupportProvider { @Override - public boolean isSafeDeleteAvailable(PsiElement element) { + public boolean isSafeDeleteAvailable(@NotNull PsiElement element) { return KotlinSafeDeleteProcessor.canDeleteElement(element); } @@ -38,7 +39,7 @@ public class JetRefactoringSupportProvider extends RefactoringSupportProvider { } @Override - public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) { + public boolean isInplaceRenameAvailable(@NotNull PsiElement element, PsiElement context) { if (element instanceof JetProperty) { JetProperty property = (JetProperty) element; if (property.isLocal()) return true; @@ -47,6 +48,16 @@ public class JetRefactoringSupportProvider extends RefactoringSupportProvider { JetFunction function = (JetFunction) element; if (function.isLocal()) return true; } + else if (element instanceof JetParameter) { + PsiElement parent = element.getParent(); + if (parent instanceof JetForExpression) { + return true; + } + if (parent instanceof JetParameterList) { + PsiElement grandparent = parent.getParent(); + return grandparent instanceof JetCatchClause || grandparent instanceof JetFunctionLiteral; + } + } return false; } diff --git a/idea/testData/refactoring/rename/inplace/ForLoop.kt b/idea/testData/refactoring/rename/inplace/ForLoop.kt new file mode 100644 index 00000000000..cf08c2998f8 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/ForLoop.kt @@ -0,0 +1,5 @@ +fun f() { + for (i in 1..2) { + println(i + i) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/ForLoop.kt.after b/idea/testData/refactoring/rename/inplace/ForLoop.kt.after new file mode 100644 index 00000000000..842049e02cb --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/ForLoop.kt.after @@ -0,0 +1,5 @@ +fun f() { + for (j in 1..2) { + println(j + j) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/FunctionLiteral.kt b/idea/testData/refactoring/rename/inplace/FunctionLiteral.kt new file mode 100644 index 00000000000..d652d6027bc --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/FunctionLiteral.kt @@ -0,0 +1,3 @@ +fun f() { + val f: (Int) -> Int = { x -> x + x } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/FunctionLiteral.kt.after b/idea/testData/refactoring/rename/inplace/FunctionLiteral.kt.after new file mode 100644 index 00000000000..eaf671c9b89 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/FunctionLiteral.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/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt b/idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt new file mode 100644 index 00000000000..105eae3a6a6 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt @@ -0,0 +1,3 @@ +fun f() { + val f = { (x: Int) -> x + x } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt.after b/idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt.after new file mode 100644 index 00000000000..ab1c823d4d4 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/FunctionLiteralParenthesis.kt.after @@ -0,0 +1,3 @@ +fun f() { + val f = { (y: Int) -> y + y } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/FunctionParameterNotInplace.kt b/idea/testData/refactoring/rename/inplace/FunctionParameterNotInplace.kt new file mode 100644 index 00000000000..ac7d50bffd4 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/FunctionParameterNotInplace.kt @@ -0,0 +1,2 @@ +fun f(a: String) { +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/GlobalFunctionNotInplace.kt b/idea/testData/refactoring/rename/inplace/GlobalFunctionNotInplace.kt new file mode 100644 index 00000000000..3c65cc2677d --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/GlobalFunctionNotInplace.kt @@ -0,0 +1,8 @@ +fun foo(a: Int) { +} + + +fun f() { + foo(1) + foo(217) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/LocalFunction.kt b/idea/testData/refactoring/rename/inplace/LocalFunction.kt new file mode 100644 index 00000000000..6cfb21172f8 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/LocalFunction.kt @@ -0,0 +1,7 @@ +fun f() { + fun foo(a: Int) { + } + + foo(1) + foo(217) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/LocalFunction.kt.after b/idea/testData/refactoring/rename/inplace/LocalFunction.kt.after new file mode 100644 index 00000000000..4174bdc07d2 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/LocalFunction.kt.after @@ -0,0 +1,7 @@ +fun f() { + fun bar(a: Int) { + } + + bar(1) + bar(217) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/LocalVal.kt b/idea/testData/refactoring/rename/inplace/LocalVal.kt new file mode 100644 index 00000000000..4693c5a9a07 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/LocalVal.kt @@ -0,0 +1,4 @@ +fun f() { + val x = 5 + println(x + x * x) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/LocalVal.kt.after b/idea/testData/refactoring/rename/inplace/LocalVal.kt.after new file mode 100644 index 00000000000..27da12fc29c --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/LocalVal.kt.after @@ -0,0 +1,4 @@ +fun f() { + val y = 5 + println(y + y * y) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/TopLevelValNotInplace.kt b/idea/testData/refactoring/rename/inplace/TopLevelValNotInplace.kt new file mode 100644 index 00000000000..9fbcc5d917b --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/TopLevelValNotInplace.kt @@ -0,0 +1,5 @@ +val x = 5 + +fun f() { + println(x + x * x) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/TryCatch.kt b/idea/testData/refactoring/rename/inplace/TryCatch.kt new file mode 100644 index 00000000000..f57465279d7 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/TryCatch.kt @@ -0,0 +1,7 @@ +fun f() { + try { + } + catch (e: Exception) { + println(e) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/inplace/TryCatch.kt.after b/idea/testData/refactoring/rename/inplace/TryCatch.kt.after new file mode 100644 index 00000000000..26e53966ff2 --- /dev/null +++ b/idea/testData/refactoring/rename/inplace/TryCatch.kt.after @@ -0,0 +1,7 @@ +fun f() { + try { + } + catch (e1: Exception) { + println(e1) + } +} \ 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 new file mode 100644 index 00000000000..068f2445530 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/InplaceRenameTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2013 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 + +import com.intellij.testFramework.LightCodeInsightTestCase +import com.intellij.codeInsight.TargetElementUtilBase +import com.intellij.testFramework.LightPlatformCodeInsightTestCase +import com.intellij.testFramework.fixtures.CodeInsightTestUtil +import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler +import kotlin.test.* +import com.intellij.lang.java.JavaRefactoringSupportProvider +import com.intellij.testFramework.TestDataProvider +import com.intellij.testFramework.LightPlatformTestCase +import com.intellij.ide.DataManager +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 + +public class InplaceRenameTest : LightCodeInsightTestCase() { + override fun isRunInWriteAction(): Boolean = false + override fun getTestDataPath(): String = PluginTestCaseBase.getTestDataPathBase() + "/refactoring/rename/inplace/" + + public fun testLocalVal() { + doTestInplaceRename("y") + } + + public fun testForLoop() { + doTestInplaceRename("j") + } + + public fun testTryCatch() { + doTestInplaceRename("e1") + } + + public fun testFunctionLiteral() { + doTestInplaceRename("y") + } + + public fun testFunctionLiteralParenthesis() { + doTestInplaceRename("y") + } + + public fun testLocalFunction() { + doTestInplaceRename("bar") + } + + public fun testFunctionParameterNotInplace() { + doTestInplaceRename(null) + } + + public fun testGlobalFunctionNotInplace() { + doTestInplaceRename(null) + } + + public fun testTopLevelValNotInplace() { + doTestInplaceRename(null) + } + + private fun doTestInplaceRename(newName: String?) { + configureByFile(getTestName(false) + ".kt") + val element = TargetElementUtilBase.findTargetElement( + LightPlatformCodeInsightTestCase.myEditor, + TargetElementUtilBase.ELEMENT_NAME_ACCEPTED or TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED + ) + + assertNotNull(element) + + val dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.getName(), element!!, + LightPlatformCodeInsightTestCase.getCurrentEditorDataContext()) + + val handler = VariableInplaceRenameHandler() + if (newName == null) { + assertFalse(handler.isRenaming(dataContext), "In-place rename is allowed for " + element) + } + else { + assertTrue(handler.isRenaming(dataContext), "In-place rename not allowed for " + element) + CodeInsightTestUtil.doInlineRename(handler, newName, LightPlatformCodeInsightTestCase.getEditor(), element) + checkResultByFile(getTestName(false) + ".kt.after") + } + } +} \ No newline at end of file