Support of KT-11255 Support Move Element Left/Right actions for Kotlin (except for enum entries)

#KT-11255 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-05-05 12:53:09 +03:00
parent 7e99a6bb45
commit 07207949ba
43 changed files with 367 additions and 16 deletions
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionT
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateTestSupportMethodActionTest
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateToStringActionTest
import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveLeftRightTest
import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveStatementTest
import org.jetbrains.kotlin.idea.codeInsight.surroundWith.AbstractSurroundWithTest
import org.jetbrains.kotlin.idea.codeInsight.unwrap.AbstractUnwrapRemoveTest
@@ -511,6 +512,10 @@ fun main(args: Array<String>) {
model("codeInsight/moveUpDown/parametersAndArguments", testMethod = "doTestExpression")
}
testClass<AbstractMoveLeftRightTest>() {
model("codeInsight/moveLeftRight")
}
testClass<AbstractInlineTest>() {
model("refactoring/inline", pattern = "^(\\w+)\\.kt$")
}
+2
View File
@@ -618,6 +618,8 @@
implementation="org.jetbrains.kotlin.idea.codeInsight.upDownMover.KotlinDeclarationMover"
order="before jetExpression" />
<moveLeftRightHandler language="kotlin" implementationClass="org.jetbrains.kotlin.idea.codeInsight.KotlinMoveLeftRightHandler"/>
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinDeclarationAndAssignmentHandler"/>
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinBlockIntoSingleStatementHandler"/>
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2016 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.kotlin.idea.codeInsight
import com.intellij.codeInsight.editorActions.moveLeftRight.MoveElementLeftRightHandler
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.*
class KotlinMoveLeftRightHandler : MoveElementLeftRightHandler() {
override fun getMovableSubElements(element: PsiElement): Array<PsiElement> {
when (element) {
is KtParameterList -> return element.parameters.toTypedArray()
is KtValueArgumentList -> return element.arguments.toTypedArray()
is KtArrayAccessExpression -> return element.indexExpressions.toTypedArray()
is KtTypeParameterList -> return element.parameters.toTypedArray()
is KtSuperTypeList -> return element.entries.toTypedArray()
//TODO
// is KtClass -> if (element.isEnum()) return element.declarations.filterIsInstance<KtEnumEntry>().toTypedArray()
}
return emptyArray()
}
}
@@ -0,0 +1,4 @@
// MOVE: right
@A(<caret>1, 2)
fun foo() {
}
@@ -0,0 +1,4 @@
// MOVE: right
@A(2, <caret>1)
fun foo() {
}
+6
View File
@@ -0,0 +1,6 @@
// MOVE: left
interface I
abstract class Base
class A : I, <caret>Base()
@@ -0,0 +1,6 @@
// MOVE: left
interface I
abstract class Base
class A : <caret>Base(), I
+4
View File
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(<caret>1, 2)
}
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(2, <caret>1)
}
+4
View File
@@ -0,0 +1,4 @@
// MOVE: left
fun foo() {
bar(1, <caret>2)
}
@@ -0,0 +1,4 @@
// MOVE: left
fun foo() {
bar(<caret>2, 1)
}
+4
View File
@@ -0,0 +1,4 @@
// MOVE: left
fun foo(list: List<String>) {
bar(1, <caret>*list)
}
@@ -0,0 +1,4 @@
// MOVE: left
fun foo(list: List<String>) {
bar(<caret>*list, 1)
}
+4
View File
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(<caret>a = 1, b = 2)
}
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(b = 2, <caret>a = 1)
}
+4
View File
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(1, <caret>2, 3)
}
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
bar(1, 3, <caret>2)
}
@@ -0,0 +1,4 @@
// MOVE: right
enum class E {
B, <caret>A, C
}
@@ -0,0 +1,4 @@
// MOVE: right
enum class E {
<caret>A, B, C
}
@@ -0,0 +1,4 @@
// MOVE: right
enum class E {
A, C, <caret>B
}
@@ -0,0 +1,4 @@
// MOVE: right
enum class E {
A, <caret>B, C
}
@@ -0,0 +1,4 @@
// MOVE: left
enum class E {
<caret>B, A, C
}
@@ -0,0 +1,4 @@
// MOVE: left
enum class E {
A, <caret>B, C
}
@@ -0,0 +1,6 @@
// MOVE: right
enum class E {
A, C, <caret>B;
fun foo(){}
}
@@ -0,0 +1,6 @@
// MOVE: right
enum class E {
A, <caret>B, C;
fun foo(){}
}
@@ -0,0 +1,8 @@
// MOVE: left
enum class E {
A, C<caret>, B
;
fun foo(){}
}
@@ -0,0 +1,8 @@
// MOVE: left
enum class E {
A, B, C<caret>
;
fun foo(){}
}
+5
View File
@@ -0,0 +1,5 @@
// MOVE: left
class A {
fun foo(b: Int, <caret>a: Int, c: Int) {
}
}
@@ -0,0 +1,5 @@
// MOVE: left
class A {
fun foo(<caret>a: Int, b: Int, c: Int) {
}
}
+5
View File
@@ -0,0 +1,5 @@
// MOVE: right
class A {
fun foo(b: Int, <caret>a: Int, c: Int) {
}
}
@@ -0,0 +1,5 @@
// MOVE: right
class A {
fun foo(b: Int, c: Int, <caret>a: Int) {
}
}
+5
View File
@@ -0,0 +1,5 @@
// MOVE: right
class A {
fun foo(<caret>b: Int, a: Int, c: Int) {
}
}
@@ -0,0 +1,5 @@
// MOVE: right
class A {
fun foo(a: Int, <caret>b: Int, c: Int) {
}
}
+5
View File
@@ -0,0 +1,5 @@
// MOVE: left
class A {
fun foo(<caret>a: Int, b: Int, c: Int) {
}
}
@@ -0,0 +1,5 @@
// MOVE: left
class A {
fun foo(<caret>a: Int, b: Int, c: Int) {
}
}
+4
View File
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
x[<caret>1, 2]
}
@@ -0,0 +1,4 @@
// MOVE: right
fun foo() {
x[2, <caret>1]
}
@@ -0,0 +1,4 @@
// MOVE: left
fun foo(list: List<String>) {
list.foldRightIndexed(1, { p1, <caret>p2, p3 -> 1 })
}
@@ -0,0 +1,4 @@
// MOVE: left
fun foo(list: List<String>) {
list.foldRightIndexed(1, { <caret>p2, p1, p3 -> 1 })
}
+3
View File
@@ -0,0 +1,3 @@
// MOVE: right
fun <<caret>T1, T2> foo() {
}
@@ -0,0 +1,3 @@
// MOVE: right
fun <T2, <caret>T1> foo() {
}
@@ -21,13 +21,15 @@ import com.intellij.codeInsight.editorActions.moveLeftRight.MoveElementRightActi
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementDownAction
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementUpAction
import com.intellij.codeInsight.editorActions.moveUpDown.StatementUpDownMover
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.actionSystem.Presentation
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.editor.actionSystem.EditorAction
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.LightCodeInsightTestCase
import com.intellij.testFramework.LightPlatformCodeInsightTestCase
import junit.framework.ComparisonFailure
import junit.framework.TestCase
import org.jetbrains.kotlin.formatter.FormatSettingsUtil
import org.jetbrains.kotlin.idea.codeInsight.upDownMover.KotlinDeclarationMover
import org.jetbrains.kotlin.idea.codeInsight.upDownMover.KotlinExpressionMover
@@ -58,8 +60,14 @@ abstract class AbstractMoveStatementTest : AbstractCodeMoverTest() {
}
}
abstract class AbstractMoveLeftRightTest : AbstractCodeMoverTest() {
protected fun doTest(path: String) {
doTest(path) { isApplicableExpected, direction -> }
}
}
abstract class AbstractCodeMoverTest : LightCodeInsightTestCase() {
protected fun doTest(path: String, isApplicableChecker: (isApplicableExpected: Boolean, direction: String) -> Unit = { isApplicableExpected, direction -> }) {
protected fun doTest(path: String, isApplicableChecker: (isApplicableExpected: Boolean, direction: String) -> Unit) {
configureByFile(path)
val fileText = FileUtil.loadFile(File(path), true)
@@ -79,29 +87,33 @@ abstract class AbstractCodeMoverTest : LightCodeInsightTestCase() {
isApplicableChecker(isApplicableExpected, direction)
if (isApplicableExpected) {
invokeAndCheck(fileText, path, action)
}
invokeAndCheck(fileText, path, action, isApplicableExpected)
}
private fun invokeAndCheck(fileText: String, path: String, action: EditorAction) {
private fun invokeAndCheck(fileText: String, path: String, action: EditorAction, isApplicableExpected: Boolean) {
val codeStyleSettings = FormatSettingsUtil.getSettings()
val configurator = FormatSettingsUtil.createConfigurator(fileText, codeStyleSettings)
configurator.configureSettings()
try {
ApplicationManager.getApplication().runWriteAction {
action.actionPerformed(LightPlatformCodeInsightTestCase.getEditor(), LightPlatformCodeInsightTestCase.getCurrentEditorDataContext())
}
val editor = LightPlatformCodeInsightTestCase.getEditor()
val dataContext = LightPlatformCodeInsightTestCase.getCurrentEditorDataContext()
val afterFilePath = path + ".after"
try {
checkResultByFile(afterFilePath)
}
catch (e: ComparisonFailure) {
KotlinTestUtils.assertEqualsToFile(File(afterFilePath), LightPlatformCodeInsightTestCase.getEditor())
}
val presentation = Presentation()
action.update(editor, presentation, dataContext)
TestCase.assertEquals(isApplicableExpected, presentation.isEnabled)
if (isApplicableExpected) {
runWriteAction { action.actionPerformed(editor, dataContext) }
val afterFilePath = path + ".after"
try {
checkResultByFile(afterFilePath)
}
catch (e: ComparisonFailure) {
KotlinTestUtils.assertEqualsToFile(File(afterFilePath), editor)
}
}
}
finally {
codeStyleSettings.clearCodeStyleSettings()
@@ -0,0 +1,121 @@
/*
* Copyright 2010-2016 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.kotlin.idea.codeInsight.moveUpDown;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/codeInsight/moveLeftRight")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class MoveLeftRightTestGenerated extends AbstractMoveLeftRightTest {
public void testAllFilesPresentInMoveLeftRight() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/moveLeftRight"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("annotationParams.kt")
public void testAnnotationParams() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/annotationParams.kt");
doTest(fileName);
}
@TestMetadata("basesList.kt")
public void testBasesList() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/basesList.kt");
doTest(fileName);
}
@TestMetadata("callArgs1.kt")
public void testCallArgs1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/callArgs1.kt");
doTest(fileName);
}
@TestMetadata("callArgs2.kt")
public void testCallArgs2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/callArgs2.kt");
doTest(fileName);
}
@TestMetadata("callArgs3.kt")
public void testCallArgs3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/callArgs3.kt");
doTest(fileName);
}
@TestMetadata("callArgs4.kt")
public void testCallArgs4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/callArgs4.kt");
doTest(fileName);
}
@TestMetadata("callArgs5.kt")
public void testCallArgs5() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/callArgs5.kt");
doTest(fileName);
}
@TestMetadata("funParams1.kt")
public void testFunParams1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/funParams1.kt");
doTest(fileName);
}
@TestMetadata("funParams2.kt")
public void testFunParams2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/funParams2.kt");
doTest(fileName);
}
@TestMetadata("funParams3.kt")
public void testFunParams3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/funParams3.kt");
doTest(fileName);
}
@TestMetadata("funParams4.kt")
public void testFunParams4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/funParams4.kt");
doTest(fileName);
}
@TestMetadata("indexArgs.kt")
public void testIndexArgs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/indexArgs.kt");
doTest(fileName);
}
@TestMetadata("lambdaParams.kt")
public void testLambdaParams() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/lambdaParams.kt");
doTest(fileName);
}
@TestMetadata("typeArgs.kt")
public void testTypeArgs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/moveLeftRight/typeArgs.kt");
doTest(fileName);
}
}