Add intention to add/remove underscores in numeric literal
#KT-28953 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
225a6ea288
commit
622fd8d8cf
@@ -1689,6 +1689,16 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.AddUnderscoresToNumericLiteralIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.RemoveUnderscoresFromNumericLiteralIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<lang.inspectionSuppressor language="kotlin" implementationClass="org.jetbrains.kotlin.idea.inspections.KotlinInspectionSuppressor"/>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection"
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
val oneMillion = <spot>1_000_000</spot>
|
||||
+1
@@ -0,0 +1 @@
|
||||
val oneMillion = <spot>1000000</spot>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention adds underscores to a numeric literal.
|
||||
</body>
|
||||
</html>
|
||||
+1
@@ -0,0 +1 @@
|
||||
val oneMillion = <spot>1000000</spot>
|
||||
+1
@@ -0,0 +1 @@
|
||||
val oneMillion = <spot>1_000_000</spot>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention removes underscores from a numeric literal.
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>(
|
||||
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>(
|
||||
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
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.intentions.AddUnderscoresToNumericLiteralIntention
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// IS_APPLICABLE: false
|
||||
val x = <caret>0b11010010011010011001010010010010
|
||||
@@ -0,0 +1 @@
|
||||
val x = <caret>12345678.9
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = 12_345_678.9
|
||||
@@ -0,0 +1 @@
|
||||
val x = <caret>12345678f
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = 12_345_678f
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// IS_APPLICABLE: false
|
||||
val x = <caret>0xFFECDE5E
|
||||
@@ -0,0 +1 @@
|
||||
val x = <caret>1234567890
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = 1_234_567_890
|
||||
@@ -0,0 +1,2 @@
|
||||
// IS_APPLICABLE: false
|
||||
val x = <caret>123
|
||||
@@ -0,0 +1 @@
|
||||
val x = 1234567890L<caret>
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = 1_234_567_890L
|
||||
@@ -0,0 +1,2 @@
|
||||
// WITH_RUNTIME
|
||||
val x = 123456<caret>7890u
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// WITH_RUNTIME
|
||||
val x = 1_234_567_890u
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.intentions.RemoveUnderscoresFromNumericLiteralIntention
|
||||
@@ -0,0 +1 @@
|
||||
val x = <caret>1_234_567_890
|
||||
+1
@@ -0,0 +1 @@
|
||||
val x = 1234567890
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// IS_APPLICABLE: false
|
||||
val x = <caret>1234567890
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user