diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml
index 752959e569a..bc772b6624a 100644
--- a/idea/resources/META-INF/plugin-common.xml
+++ b/idea/resources/META-INF/plugin-common.xml
@@ -1381,6 +1381,11 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.ConvertSnakeCaseTestFunctionToSpacedIntention
+ Kotlin
+
+
org.jetbrains.kotlin.idea.intentions.ReplaceSingleLineLetIntention
Kotlin
diff --git a/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/after.kt.template b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/after.kt.template
new file mode 100644
index 00000000000..306191852a9
--- /dev/null
+++ b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/after.kt.template
@@ -0,0 +1,5 @@
+class MyTest {
+ @Test fun `test two plus two equals four`() {
+
+ }
+}
diff --git a/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/before.kt.template b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/before.kt.template
new file mode 100644
index 00000000000..d21da9a8ff5
--- /dev/null
+++ b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/before.kt.template
@@ -0,0 +1,5 @@
+class MyTest {
+ @Test fun test_two_plus_two_equals_four() {
+
+ }
+}
diff --git a/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/description.html b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/description.html
new file mode 100644
index 00000000000..4b912cd5300
--- /dev/null
+++ b/idea/resources/intentionDescriptions/ConvertSnakeCaseTestFunctionToSpacedIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention changes a snake case name of the given test function to a space-separated one.
+
+
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCamelCaseTestFunctionToSpacedIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTestFunctionToSpacedIntention.kt
similarity index 62%
rename from idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCamelCaseTestFunctionToSpacedIntention.kt
rename to idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTestFunctionToSpacedIntention.kt
index bfdb3041252..2ca87f1ef6a 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertCamelCaseTestFunctionToSpacedIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTestFunctionToSpacedIntention.kt
@@ -37,16 +37,29 @@ import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
import org.jetbrains.kotlin.utils.SmartList
-class ConvertCamelCaseTestFunctionToSpacedIntention : SelfTargetingRangeIntention(
- KtNamedFunction::class.java, "Replace camel-case name with spaces"
+sealed class ConvertTestFunctionToSpacedIntention(case: String) : SelfTargetingRangeIntention(
+ KtNamedFunction::class.java, "Replace $case name with spaces"
) {
+ companion object {
+ private val SNAKE_CASE_REGEX = ".+_.+".toRegex()
+ }
+
+ abstract fun split(name: String): List
+
+ abstract fun isApplicableName(name: String): Boolean
+
+ protected fun isSnakeCase(name: String): Boolean {
+ return name.contains(SNAKE_CASE_REGEX)
+ }
+
override fun applicabilityRange(element: KtNamedFunction): TextRange? {
val platform = element.platform
if (platform is CommonPlatform || platform is JsPlatform) return null
val range = element.nameIdentifier?.textRange ?: return null
val name = element.name ?: return null
- val newName = decamelize(name)
+ if (!isApplicableName(name)) return null
+ val newName = convert(name)
if (newName == name.quoteIfNeeded()) return null
val lightMethod = element.toLightMethods().firstOrNull() ?: return null
@@ -57,11 +70,67 @@ class ConvertCamelCaseTestFunctionToSpacedIntention : SelfTargetingRangeIntentio
return range
}
+ private fun convert(name: String) = split(name).joinToString(separator = " ") { it.decapitalizeSmart().trim() }.quoteIfNeeded()
+
+ private fun startRename(element: KtNamedFunction, newName: String) {
+ RenameProcessor(element.project, element, newName, false, false).run()
+ }
+
+ override fun startInWriteAction() = false
+
+ override fun applyTo(element: KtNamedFunction, editor: Editor?) {
+ val nameIdentifier = element.nameIdentifier ?: return
+ val oldName = element.name ?: return
+ val oldId = oldName.quoteIfNeeded()
+ val newId = convert(oldName)
+
+ if (editor != null) {
+ val builder = TemplateBuilderImpl(nameIdentifier)
+ builder.replaceElement(nameIdentifier, newId)
+ val template = runWriteAction { builder.buildInlineTemplate() }
+ TemplateManager.getInstance(element.project).startTemplate(
+ editor,
+ template,
+ object : TemplateEditingAdapter() {
+ private var chosenId: String = newId
+ private var range: TextRange? = null
+
+ override fun beforeTemplateFinished(state: TemplateState, template: Template?) {
+ val varName = (template as? TemplateImpl)?.getVariableNameAt(0) ?: return
+ chosenId = state.getVariableValue(varName)?.text?.quoteIfNeeded() ?: return
+ range = state.getVariableRange(varName)
+ }
+
+ override fun templateFinished(template: Template, brokenOff: Boolean) {
+ range?.let {
+ val doc = editor.document
+ runWriteAction { doc.replaceString(it.startOffset, it.endOffset, oldId) }
+ PsiDocumentManager.getInstance(element.project).commitDocument(doc)
+ }
+
+ if (!brokenOff && chosenId != oldId) {
+ startRename(element, chosenId)
+ }
+ }
+ }
+ )
+ } else {
+ startRename(element, newId)
+ }
+ }
+}
+
+
+class ConvertCamelCaseTestFunctionToSpacedIntention : ConvertTestFunctionToSpacedIntention("camel-case") {
+ override fun isApplicableName(name: String): Boolean {
+ return !isSnakeCase(name)
+ }
+
enum class Case {
LOWER, UPPER, OTHER
}
- private fun splitCamelName(name: String): List {
+ override fun split(name: String): List {
if (name === "") return emptyList()
val result = SmartList()
@@ -88,54 +157,14 @@ class ConvertCamelCaseTestFunctionToSpacedIntention : SelfTargetingRangeIntentio
return result
}
+}
- private fun decamelize(name: String) = splitCamelName(name).joinToString(separator = " ") { it.decapitalizeSmart().trim() }.quoteIfNeeded()
-
- private fun startRename(element: KtNamedFunction, newName: String) {
- RenameProcessor(element.project, element, newName, false, false).run()
+class ConvertSnakeCaseTestFunctionToSpacedIntention : ConvertTestFunctionToSpacedIntention("snake_case") {
+ override fun isApplicableName(name: String): Boolean {
+ return isSnakeCase(name)
}
- override fun startInWriteAction() = false
-
- override fun applyTo(element: KtNamedFunction, editor: Editor?) {
- val nameIdentifier = element.nameIdentifier ?: return
- val oldName = element.name ?: return
- val oldId = oldName.quoteIfNeeded()
- val newId = decamelize(oldName)
-
- if (editor != null) {
- val builder = TemplateBuilderImpl(nameIdentifier)
- builder.replaceElement(nameIdentifier, newId)
- val template = runWriteAction { builder.buildInlineTemplate() }
- TemplateManager.getInstance(element.project).startTemplate(
- editor,
- template,
- object : TemplateEditingAdapter() {
- private var chosenId: String = newId
- private var range: TextRange? = null
-
- override fun beforeTemplateFinished(state: TemplateState, template: Template?) {
- val varName = (template as? TemplateImpl)?.getVariableNameAt(0) ?: return
- chosenId = state?.getVariableValue(varName)?.text?.quoteIfNeeded() ?: return
- range = state.getVariableRange(varName)
- }
-
- override fun templateFinished(template: Template, brokenOff: Boolean) {
- range?.let {
- val doc = editor.document
- runWriteAction { doc.replaceString(it.startOffset, it.endOffset, oldId) }
- PsiDocumentManager.getInstance(element.project).commitDocument(doc)
- }
-
- if (!brokenOff && chosenId != oldId) {
- startRename(element, chosenId)
- }
- }
- }
- )
- }
- else {
- startRename(element, newId)
- }
+ override fun split(name: String): List {
+ return name.split("_").filter { it.isNotBlank() }
}
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/snake.kt b/idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/snake.kt
new file mode 100644
index 00000000000..0f1e16b57dd
--- /dev/null
+++ b/idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/snake.kt
@@ -0,0 +1,12 @@
+// CONFIGURE_LIBRARY: JUnit@lib/junit-4.12.jar
+// IS_APPLICABLE: false
+
+import org.junit.Test
+
+class A {
+ @Test fun test_two_plus_two_equals_four() {}
+}
+
+fun test() {
+ A().test_two_plus_two_equals_four()
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/.intention b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/.intention
new file mode 100644
index 00000000000..ed522d9135b
--- /dev/null
+++ b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.ConvertSnakeCaseTestFunctionToSpacedIntention
diff --git a/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/camel.kt b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/camel.kt
new file mode 100644
index 00000000000..dda9357766d
--- /dev/null
+++ b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/camel.kt
@@ -0,0 +1,8 @@
+// CONFIGURE_LIBRARY: JUnit@lib/junit-4.12.jar
+// IS_APPLICABLE: false
+
+import org.junit.Test
+
+class A {
+ @Test fun testTwoPlusTwoEqualsFour() {}
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt
new file mode 100644
index 00000000000..a9e3ef79d29
--- /dev/null
+++ b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt
@@ -0,0 +1,10 @@
+// CONFIGURE_LIBRARY: JUnit@lib/junit-4.12.jar
+import org.junit.Test
+
+class A {
+ @Test fun test_two_plus_two_equals_four() {}
+}
+
+fun test() {
+ A().test_two_plus_two_equals_four()
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt.after b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt.after
new file mode 100644
index 00000000000..bf442c2cb5b
--- /dev/null
+++ b/idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt.after
@@ -0,0 +1,10 @@
+// CONFIGURE_LIBRARY: JUnit@lib/junit-4.12.jar
+import org.junit.Test
+
+class A {
+ @Test fun `test two plus two equals four`() {}
+}
+
+fun test() {
+ A().`test two plus two equals four`()
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
index 086e019311e..febfb26c42f 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -4804,6 +4804,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/notTestFunction.kt");
}
+ @TestMetadata("snake.kt")
+ public void testSnake() throws Exception {
+ runTest("idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/snake.kt");
+ }
+
@TestMetadata("unchanged.kt")
public void testUnchanged() throws Exception {
runTest("idea/testData/intentions/convertCamelCaseTestFunctionToSpaced/unchanged.kt");
@@ -7014,6 +7019,29 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ConvertSnakeCaseTestFunctionToSpaced extends AbstractIntentionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInConvertSnakeCaseTestFunctionToSpaced() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("camel.kt")
+ public void testCamel() throws Exception {
+ runTest("idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/camel.kt");
+ }
+
+ @TestMetadata("snake.kt")
+ public void testSnake() throws Exception {
+ runTest("idea/testData/intentions/convertSnakeCaseTestFunctionToSpaced/snake.kt");
+ }
+ }
+
@TestMetadata("idea/testData/intentions/convertToAlso")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)