diff --git a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt index 874a802a76ed..3f2530925115 100644 --- a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt +++ b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt @@ -4,6 +4,7 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.config.ApiVersion.Companion.KOTLIN_1_8 import org.jetbrains.kotlin.nj2k.* import org.jetbrains.kotlin.nj2k.conversions.ReplaceType.REPLACE_SELECTOR import org.jetbrains.kotlin.nj2k.conversions.ReplaceType.REPLACE_WITH_QUALIFIER @@ -243,7 +244,8 @@ private class ConversionsHolder(private val symbolProvider: JKSymbolProvider, pr throwableConversions + stringConversions + arrayConversions + - printlnConversions + printlnConversions + + mathConversions return conversions.groupBy { it.from.fqName } } @@ -771,6 +773,49 @@ private class ConversionsHolder(private val symbolProvider: JKSymbolProvider, pr withFilter ::isSystemOutCall ) + private val mathConversions: List = listOf( + Method("java.lang.Math.abs") convertTo Method("kotlin.math.abs") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.acos") convertTo Method("kotlin.math.acos") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.asin") convertTo Method("kotlin.math.asin") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.atan") convertTo Method("kotlin.math.atan") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.atan2") convertTo Method("kotlin.math.atan2") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.cbrt") convertTo Method("kotlin.math.cbrt") withReplaceType REPLACE_WITH_QUALIFIER sinceKotlin KOTLIN_1_8, + Method("java.lang.Math.ceil") convertTo Method("kotlin.math.ceil") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.cos") convertTo Method("kotlin.math.cos") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.cosh") convertTo Method("kotlin.math.cosh") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.exp") convertTo Method("kotlin.math.exp") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.expm1") convertTo Method("kotlin.math.expm1") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.floor") convertTo Method("kotlin.math.floor") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.hypot") convertTo Method("kotlin.math.hypot") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.IEEEremainder") convertTo ExtensionMethod("kotlin.math.IEEErem") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.log") convertTo Method("kotlin.math.ln") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.log1p") convertTo Method("kotlin.math.ln1p") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.log10") convertTo Method("kotlin.math.log10") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.max") convertTo Method("kotlin.math.max") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.min") convertTo Method("kotlin.math.min") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.nextDown") convertTo ExtensionMethod("kotlin.math.nextDown") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.nextAfter") convertTo ExtensionMethod("kotlin.math.nextTowards") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.nextUp") convertTo ExtensionMethod("kotlin.math.nextUp") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.pow") convertTo ExtensionMethod("kotlin.math.pow") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.rint") convertTo Method("kotlin.math.round") withReplaceType REPLACE_WITH_QUALIFIER, + + Method("java.lang.Math.round") convertTo CustomExpression { expression: JKExpression -> + val arguments = (expression as JKCallExpression).arguments + if (arguments.arguments.isEmpty()) return@CustomExpression expression + val firstArgument = arguments.arguments[0]::value.detached() + val method = if (firstArgument.isDoubleType()) "roundToLong" else "roundToInt" + firstArgument.callOn(symbolProvider.provideMethodSymbol("kotlin.math.$method")).withFormattingFrom(expression) + } withReplaceType REPLACE_WITH_QUALIFIER, + + Method("java.lang.Math.signum") convertTo Method("kotlin.math.sign") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.sin") convertTo Method("kotlin.math.sin") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.sinh") convertTo Method("kotlin.math.sinh") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.sqrt") convertTo Method("kotlin.math.sqrt") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.tan") convertTo Method("kotlin.math.tan") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.tanh") convertTo Method("kotlin.math.tanh") withReplaceType REPLACE_WITH_QUALIFIER, + Method("java.lang.Math.copySign") convertTo ExtensionMethod("kotlin.math.withSign") withReplaceType REPLACE_WITH_QUALIFIER, + ) + private fun castReceiverToJavaLangObject(): CustomExpression = CustomExpression { expr -> val parent = expr.parent ?: return@CustomExpression expr val (receiver, selector) = if (parent is JKQualifiedExpression) { @@ -895,4 +940,7 @@ private class ConversionsHolder(private val symbolProvider: JKSymbolProvider, pr private fun List.containsNull(): Boolean = any { it.isNull() } + + private fun JKExpression?.isDoubleType(): Boolean = + this?.calculateType(typeFactory) == JKJavaPrimitiveType.DOUBLE } diff --git a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java index dfbc0eecc262..5b1d0beb7143 100644 --- a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java +++ b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java @@ -2639,6 +2639,16 @@ public abstract class NewJavaToKotlinConverterSingleFileTestGenerated extends Ab runTest("testData/newJ2k/function/mainVararg.java"); } + @TestMetadata("mathCbrt17ApiVersion.java") + public void testMathCbrt17ApiVersion() throws Exception { + runTest("testData/newJ2k/function/mathCbrt17ApiVersion.java"); + } + + @TestMetadata("mathStaticMethods.java") + public void testMathStaticMethods() throws Exception { + runTest("testData/newJ2k/function/mathStaticMethods.java"); + } + @TestMetadata("methodClassType.java") public void testMethodClassType() throws Exception { runTest("testData/newJ2k/function/methodClassType.java"); diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.java new file mode 100644 index 000000000000..3430d564454e --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.java @@ -0,0 +1,6 @@ +// API_VERSION: 1.7 +public class J { + void foo(Double x) { + Math.cbrt(x); + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.kt new file mode 100644 index 000000000000..fa65f65b9762 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathCbrt17ApiVersion.kt @@ -0,0 +1,6 @@ +// API_VERSION: 1.7 +class J { + fun foo(x: Double?) { + Math.cbrt(x!!) + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.java new file mode 100644 index 000000000000..4beaf3936c8a --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.java @@ -0,0 +1,38 @@ +// TODO investigate why extension methods are unresolved in this test (imports are not added) +public class J { + void foo(double x, double y, float f) { + Math.abs(x); + Math.acos(x); + Math.asin(x); + Math.atan(x); + Math.atan2(x, y); + Math.cbrt(x); + Math.ceil(x); + Math.copySign(x, y); + Math.cos(x); + Math.cosh(x); + Math.exp(x); + Math.expm1(x); + Math.floor(x); + Math.hypot(x, y); + Math.IEEEremainder(x, y); + Math.log(x); + Math.log1p(x); + Math.log10(x); + Math.max(x, y); + Math.min(x, y); + Math.nextAfter(x, y); + Math.nextDown(x); + Math.nextUp(x); + Math.pow(x, y); + Math.rint(x); + Math.round(x); + Math.round(f); + Math.signum(x); + Math.sin(x); + Math.sinh(x); + Math.sqrt(x); + Math.tan(x); + Math.tanh(x); + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.kt new file mode 100644 index 000000000000..0896d9a7e5ce --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/function/mathStaticMethods.kt @@ -0,0 +1,72 @@ +// ERROR: Unresolved reference: withSign +// ERROR: Unresolved reference: IEEErem +// ERROR: Unresolved reference: nextTowards +// ERROR: Unresolved reference: nextDown +// ERROR: Unresolved reference: nextUp +// ERROR: Unresolved reference: pow +// ERROR: Unresolved reference: roundToLong +// ERROR: Unresolved reference: roundToInt +import kotlin.math.abs +import kotlin.math.acos +import kotlin.math.asin +import kotlin.math.atan +import kotlin.math.atan2 +import kotlin.math.cbrt +import kotlin.math.ceil +import kotlin.math.cos +import kotlin.math.cosh +import kotlin.math.exp +import kotlin.math.expm1 +import kotlin.math.floor +import kotlin.math.hypot +import kotlin.math.ln +import kotlin.math.ln1p +import kotlin.math.log10 +import kotlin.math.max +import kotlin.math.min +import kotlin.math.round +import kotlin.math.sign +import kotlin.math.sin +import kotlin.math.sinh +import kotlin.math.sqrt +import kotlin.math.tan +import kotlin.math.tanh + +// TODO investigate why extension methods are unresolved in this test (imports are not added) +class J { + fun foo(x: Double, y: Double, f: Float) { + abs(x) + acos(x) + asin(x) + atan(x) + atan2(x, y) + cbrt(x) + ceil(x) + x.withSign(y) + cos(x) + cosh(x) + exp(x) + expm1(x) + floor(x) + hypot(x, y) + x.IEEErem(y) + ln(x) + ln1p(x) + log10(x) + max(x, y) + min(x, y) + x.nextTowards(y) + x.nextDown() + x.nextUp() + x.pow(y) + round(x) + x.roundToLong() + f.roundToInt() + sign(x) + sin(x) + sinh(x) + sqrt(x) + tan(x) + tanh(x) + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/literalExpression/double.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/literalExpression/double.kt index a3495d6deac7..3097e14f0e4d 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/literalExpression/double.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/literalExpression/double.kt @@ -1,3 +1,5 @@ +import kotlin.math.sqrt + internal class A { private var d1 = 1.0 private var d2 = 1.0 @@ -5,7 +7,7 @@ internal class A { private val d4 = 1.0 private val d5 = 1.0 private val d6 = 1.0 - private val d7 = Math.sqrt(2.0) - 1 + private val d7 = sqrt(2.0) - 1 private val d8 = 1.0 private val d9 = 1.0 private val x = 1 / (1.0 + 0)