From 622fd8d8cf144100d7301a33cb385171b136c0a6 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Mon, 7 Jan 2019 07:10:27 +0900 Subject: [PATCH] Add intention to add/remove underscores in numeric literal #KT-28953 Fixed --- idea/resources/META-INF/plugin-common.xml | 10 +++ .../after.kt.template | 1 + .../before.kt.template | 1 + .../description.html | 5 ++ .../after.kt.template | 1 + .../before.kt.template | 1 + .../description.html | 5 ++ .../UnderscoresInNumericLiteralIntention.kt | 52 +++++++++++ .../addUnderscores/.intention | 1 + .../addUnderscores/binaries.kt | 2 + .../addUnderscores/double.kt | 1 + .../addUnderscores/double.kt.after | 1 + .../addUnderscores/float.kt | 1 + .../addUnderscores/float.kt.after | 1 + .../addUnderscores/hexadecimals.kt | 2 + .../addUnderscores/int.kt | 1 + .../addUnderscores/int.kt.after | 1 + .../addUnderscores/int2.kt | 2 + .../addUnderscores/long.kt | 1 + .../addUnderscores/long.kt.after | 1 + .../addUnderscores/uInt.kt | 2 + .../addUnderscores/uInt.kt.after | 2 + .../removeUnderscores/.intention | 1 + .../removeUnderscores/int.kt | 1 + .../removeUnderscores/int.kt.after | 1 + .../removeUnderscores/noUnderscores.kt | 2 + .../intentions/IntentionTestGenerated.java | 89 +++++++++++++++++++ 27 files changed, 189 insertions(+) create mode 100644 idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/description.html create mode 100644 idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/description.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/UnderscoresInNumericLiteralIntention.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/.intention create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/binaries.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/hexadecimals.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int2.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/.intention create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt.after create mode 100644 idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/noUnderscores.kt diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index cae3aa6386c..c3f461a50fd 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -1689,6 +1689,16 @@ Kotlin + + org.jetbrains.kotlin.idea.intentions.AddUnderscoresToNumericLiteralIntention + Kotlin + + + + org.jetbrains.kotlin.idea.intentions.RemoveUnderscoresFromNumericLiteralIntention + Kotlin + + 1_000_000 \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/before.kt.template b/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/before.kt.template new file mode 100644 index 00000000000..d5744460143 --- /dev/null +++ b/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/before.kt.template @@ -0,0 +1 @@ +val oneMillion = 1000000 \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/description.html b/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/description.html new file mode 100644 index 00000000000..45e9ff447aa --- /dev/null +++ b/idea/resources/intentionDescriptions/AddUnderscoresToNumericLiteralIntention/description.html @@ -0,0 +1,5 @@ + + +This intention adds underscores to a numeric literal. + + \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/after.kt.template b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/after.kt.template new file mode 100644 index 00000000000..d5744460143 --- /dev/null +++ b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/after.kt.template @@ -0,0 +1 @@ +val oneMillion = 1000000 \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/before.kt.template b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/before.kt.template new file mode 100644 index 00000000000..74eab1fdd65 --- /dev/null +++ b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/before.kt.template @@ -0,0 +1 @@ +val oneMillion = 1_000_000 \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/description.html b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/description.html new file mode 100644 index 00000000000..5ad629bbfdd --- /dev/null +++ b/idea/resources/intentionDescriptions/RemoveUnderscoresFromNumericLiteralIntention/description.html @@ -0,0 +1,5 @@ + + +This intention removes underscores from a numeric literal. + + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/UnderscoresInNumericLiteralIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/UnderscoresInNumericLiteralIntention.kt new file mode 100644 index 00000000000..50505b5473b --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/UnderscoresInNumericLiteralIntention.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.intentions + +import com.intellij.openapi.editor.Editor +import org.jetbrains.kotlin.psi.KtConstantExpression +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.stubs.ConstantValueKind +import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType + +class AddUnderscoresToNumericLiteralIntention : SelfTargetingIntention( + KtConstantExpression::class.java, "Add underscores" +) { + override fun isApplicableTo(element: KtConstantExpression, caretOffset: Int): Boolean { + val text = element.text + return element.isNumeric() && !text.hasUnderscore() && text.takeWhile { it.isDigit() }.length > 3 + } + + override fun applyTo(element: KtConstantExpression, editor: Editor?) { + val text = element.text + val digits = text.takeWhile { it.isDigit() } + element.replace( + KtPsiFactory(element).createExpression( + digits.reversed().chunked(3).joinToString(separator = "_").reversed() + text.removePrefix(digits) + ) + ) + } +} + +class RemoveUnderscoresFromNumericLiteralIntention : SelfTargetingIntention( + KtConstantExpression::class.java, "Remove underscores" +) { + override fun isApplicableTo(element: KtConstantExpression, caretOffset: Int): Boolean { + return element.isNumeric() && element.text.hasUnderscore() + } + + override fun applyTo(element: KtConstantExpression, editor: Editor?) { + element.replace(KtPsiFactory(element).createExpression(element.text.replace("_", ""))) + } +} + +private fun KtConstantExpression.isNumeric(): Boolean = elementType in numericConstantKinds + +private val numericConstantKinds = listOf( + KtConstantExpressionElementType.kindToConstantElementType(ConstantValueKind.INTEGER_CONSTANT), + KtConstantExpressionElementType.kindToConstantElementType(ConstantValueKind.FLOAT_CONSTANT) +) + +private fun String.hasUnderscore(): Boolean = indexOf('_') != -1 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/.intention b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/.intention new file mode 100644 index 00000000000..e9b4ac72cff --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/.intention @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.AddUnderscoresToNumericLiteralIntention diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/binaries.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/binaries.kt new file mode 100644 index 00000000000..26d71777a80 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/binaries.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +val x = 0b11010010011010011001010010010010 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt new file mode 100644 index 00000000000..a289440b3ff --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt @@ -0,0 +1 @@ +val x = 12345678.9 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt.after new file mode 100644 index 00000000000..244b5ba3025 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt.after @@ -0,0 +1 @@ +val x = 12_345_678.9 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt new file mode 100644 index 00000000000..67ef05f5528 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt @@ -0,0 +1 @@ +val x = 12345678f \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt.after new file mode 100644 index 00000000000..74ca09d04cc --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt.after @@ -0,0 +1 @@ +val x = 12_345_678f \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/hexadecimals.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/hexadecimals.kt new file mode 100644 index 00000000000..ea80bfb95e0 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/hexadecimals.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +val x = 0xFFECDE5E \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt new file mode 100644 index 00000000000..7bb8856cd47 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt @@ -0,0 +1 @@ +val x = 1234567890 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt.after new file mode 100644 index 00000000000..703c160c701 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt.after @@ -0,0 +1 @@ +val x = 1_234_567_890 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int2.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int2.kt new file mode 100644 index 00000000000..7051c261a53 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int2.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +val x = 123 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt new file mode 100644 index 00000000000..52813154e46 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt @@ -0,0 +1 @@ +val x = 1234567890L \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt.after new file mode 100644 index 00000000000..661d41950d0 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt.after @@ -0,0 +1 @@ +val x = 1_234_567_890L \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt new file mode 100644 index 00000000000..ea1b1bab72f --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt @@ -0,0 +1,2 @@ +// WITH_RUNTIME +val x = 1234567890u \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt.after new file mode 100644 index 00000000000..dfc8485cb58 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt.after @@ -0,0 +1,2 @@ +// WITH_RUNTIME +val x = 1_234_567_890u \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/.intention b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/.intention new file mode 100644 index 00000000000..e272cba4264 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/.intention @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.RemoveUnderscoresFromNumericLiteralIntention diff --git a/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt new file mode 100644 index 00000000000..b6b78d33688 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt @@ -0,0 +1 @@ +val x = 1_234_567_890 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt.after b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt.after new file mode 100644 index 00000000000..19e01949429 --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt.after @@ -0,0 +1 @@ +val x = 1234567890 \ No newline at end of file diff --git a/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/noUnderscores.kt b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/noUnderscores.kt new file mode 100644 index 00000000000..9c4010a4e8e --- /dev/null +++ b/idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/noUnderscores.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +val x = 1234567890 \ 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 166e564618e..35fab2613a5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -16619,6 +16619,95 @@ public class IntentionTestGenerated extends AbstractIntentionTest { } } + @TestMetadata("idea/testData/intentions/underscoresInNumericLiteral") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnderscoresInNumericLiteral extends AbstractIntentionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInUnderscoresInNumericLiteral() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/underscoresInNumericLiteral"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddUnderscores extends AbstractIntentionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInAddUnderscores() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("binaries.kt") + public void testBinaries() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/binaries.kt"); + } + + @TestMetadata("double.kt") + public void testDouble() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/double.kt"); + } + + @TestMetadata("float.kt") + public void testFloat() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/float.kt"); + } + + @TestMetadata("hexadecimals.kt") + public void testHexadecimals() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/hexadecimals.kt"); + } + + @TestMetadata("int.kt") + public void testInt() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int.kt"); + } + + @TestMetadata("int2.kt") + public void testInt2() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/int2.kt"); + } + + @TestMetadata("long.kt") + public void testLong() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/long.kt"); + } + + @TestMetadata("uInt.kt") + public void testUInt() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/addUnderscores/uInt.kt"); + } + } + + @TestMetadata("idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class RemoveUnderscores extends AbstractIntentionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRemoveUnderscores() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("int.kt") + public void testInt() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/int.kt"); + } + + @TestMetadata("noUnderscores.kt") + public void testNoUnderscores() throws Exception { + runTest("idea/testData/intentions/underscoresInNumericLiteral/removeUnderscores/noUnderscores.kt"); + } + } + } + @TestMetadata("idea/testData/intentions/usePropertyAccessSyntax") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)