From 352fbceb0577d76e3744a4b7fd0aae462b2b9fa0 Mon Sep 17 00:00:00 2001 From: Alexey Belkov Date: Mon, 29 May 2023 12:27:18 +0400 Subject: [PATCH] [kotlin] "Java methods should be replaced with Kotlin analog": fix toString with radix ^KTIJ-25660 Fixed GitOrigin-RevId: 71ef244b3e5fd69b4b270c67df23a1eccd09388b --- ...ceJavaStaticMethodWithKotlinAnalogInspection.kt | 14 +++++++++++++- .../inspections/LocalInspectionTestGenerated.java | 10 ++++++++++ .../toString/intToString2.kt | 1 + .../toString/intToString2.kt.after | 1 + .../toString/intToStringWithInvalidLiteralRadix.kt | 5 +++++ .../toString/intToStringWithLiteralRadix.kt | 5 +++++ .../toString/intToStringWithLiteralRadix.kt.after | 5 +++++ .../toString/longToString2.kt | 4 +++- .../toString/longToString2.kt.after | 4 +++- 9 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithInvalidLiteralRadix.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt.after diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/jdk2k/ReplaceJavaStaticMethodWithKotlinAnalogInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/jdk2k/ReplaceJavaStaticMethodWithKotlinAnalogInspection.kt index 23009e435ec9..f5a2686225f9 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/jdk2k/ReplaceJavaStaticMethodWithKotlinAnalogInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/jdk2k/ReplaceJavaStaticMethodWithKotlinAnalogInspection.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKot import org.jetbrains.kotlin.idea.inspections.collections.isCalling import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtConstantExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.callExpressionVisitor import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression @@ -87,8 +88,19 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti "Float" to "Float" ).flatMap { (javaPrimitive, kotlinPrimitive) -> listOf( + // If radix is not a literal, it is considered an unsafe replacement (Kotlin has checks for an invalid radix) + Replacement("java.lang.$javaPrimitive.toString", "kotlin.text.toString", ToExtensionFunctionWithNonNullableReceiver, mayChangeSemantics = true) { + if (it.valueArguments.size != 2) return@Replacement false + val radix = it.valueArguments.last().getArgumentExpression() + radix !is KtConstantExpression + }, + // If radix is an int literal within bounds, the conversion is safe Replacement("java.lang.$javaPrimitive.toString", "kotlin.text.toString", ToExtensionFunctionWithNonNullableReceiver) { - it.valueArguments.size == 2 + if (it.valueArguments.size != 2) return@Replacement false + val radixExpr = it.valueArguments.last().getArgumentExpression() + if (radixExpr !is KtConstantExpression) return@Replacement false + val radix = radixExpr.text.toIntOrNull() ?: return@Replacement false + radix in 2..36 }, Replacement( "java.lang.$javaPrimitive.toString", diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 7888c29c82c6..fed35141553d 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -12739,6 +12739,16 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti runTest("testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt"); } + @TestMetadata("intToStringWithInvalidLiteralRadix.kt") + public void testIntToStringWithInvalidLiteralRadix() throws Exception { + runTest("testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithInvalidLiteralRadix.kt"); + } + + @TestMetadata("intToStringWithLiteralRadix.kt") + public void testIntToStringWithLiteralRadix() throws Exception { + runTest("testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt"); + } + @TestMetadata("longToString.kt") public void testLongToString() throws Exception { runTest("testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString.kt"); diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt index 725720b514c2..7fd2a48d1549 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with 'toString' function (may change semantics) fun foo() { val b = listOf(42, 10) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt.after index 119a6be00ef9..4dc7a6a6ca9d 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToString2.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with 'toString' function (may change semantics) fun foo() { val b = listOf(42, 10) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithInvalidLiteralRadix.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithInvalidLiteralRadix.kt new file mode 100644 index 000000000000..b839ba982aaf --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithInvalidLiteralRadix.kt @@ -0,0 +1,5 @@ +// WITH_STDLIB +// PROBLEM: none +fun foo() { + Integer.toString(42, 1) +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt new file mode 100644 index 000000000000..8708150f0ecf --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt @@ -0,0 +1,5 @@ +// WITH_STDLIB + +fun foo() { + Integer.toString(42, 8) +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt.after new file mode 100644 index 000000000000..145e33b86f0d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/intToStringWithLiteralRadix.kt.after @@ -0,0 +1,5 @@ +// WITH_STDLIB + +fun foo() { + 42.toString(8) +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt index 67496771bbe4..2b264ccdc712 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt @@ -1,5 +1,7 @@ // WITH_STDLIB +// FIX: Replace with 'toString' function (may change semantics) fun foo() { - val t = java.lang.Long.toString(5, 42) + 6 + val radix = 42 + val t = java.lang.Long.toString(5, radix) + 6 } diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt.after index 8d15bf3ae418..f00b804734b3 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/toString/longToString2.kt.after @@ -1,5 +1,7 @@ // WITH_STDLIB +// FIX: Replace with 'toString' function (may change semantics) fun foo() { - val t = 5.toString(42) + 6 + val radix = 42 + val t = 5.toString(radix) + 6 }