ReplaceJavaStaticMethodWithKotlinAnalogInspection: introduce Transform interface

#KT-32454 Fixed
This commit is contained in:
Dmitry Gridin
2019-07-09 11:53:10 +03:00
parent 835532c206
commit 3aa2401f19
45 changed files with 169 additions and 230 deletions
@@ -9,49 +9,36 @@ import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.inspections.collections.isCalling import org.jetbrains.kotlin.idea.inspections.collections.isCalling
import org.jetbrains.kotlin.idea.intentions.callExpression import org.jetbrains.kotlin.idea.util.textRangeIn
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.callExpressionVisitor
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspection() { class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = callExpressionVisitor(fun(call) { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = callExpressionVisitor(fun(call) {
val callee = call.calleeExpression ?: return val callee = call.calleeExpression ?: return
val dotQualified = call.getStrictParentOfType<KtDotQualifiedExpression>() ?: return
val replacements = REPLACEMENTS[callee.text] val replacements = REPLACEMENTS[callee.text]
?.filter { it.filter(call) } ?.filter { it.filter(call) && it.transformation.isApplicable(call) }
?.takeIf { it.isNotEmpty() } ?.takeIf { it.isNotEmpty() }
?.let { list -> ?.let { list ->
val callDescriptor = call.getResolvedCall(call.analyze(BodyResolveMode.PARTIAL)) ?: return val callDescriptor = call.getResolvedCall(call.analyze(BodyResolveMode.PARTIAL)) ?: return
list.filter { list.filter { callDescriptor.isCalling(FqName(it.javaMethodFqName)) }
callDescriptor.isCalling(FqName(it.javaMethodFqName)) && (!it.toExtensionFunction || call.valueArguments.isNotEmpty())
}
} }
?.takeIf { it.isNotEmpty() } ?.takeIf { it.isNotEmpty() }
?.map { ?.map(::ReplaceWithKotlinAnalogFunction)
ReplaceWithKotlinAnalogFunction(
it
)
}
?.toTypedArray() ?: return ?.toTypedArray() ?: return
holder.registerProblem( holder.registerProblem(
dotQualified, call,
TextRange(0, callee.endOffset - dotQualified.startOffset), callee.textRangeIn(call),
"Should be replaced with Kotlin function", "Should be replaced with Kotlin function",
*replacements *replacements
) )
@@ -63,28 +50,8 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti
override fun getFamilyName() = "Replace with Kotlin analog" override fun getFamilyName() = "Replace with Kotlin analog"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val dotQualified = descriptor.psiElement as? KtDotQualifiedExpression ?: return val callExpression = descriptor.psiElement as? KtCallExpression ?: return
val call = dotQualified.callExpression ?: return replacement.transformation(callExpression, replacement)
val file = dotQualified.containingKtFile
val psiFactory = KtPsiFactory(call)
val valueArguments = call.valueArguments
val typeArguments = call.typeArgumentList?.text ?: ""
if (replacement.toExtensionFunction) {
val receiverText = valueArguments.first().getArgumentExpression()
?.run { if (this is KtOperationExpression) "($text)" else text }
?: valueArguments.first().text
val argumentsText = valueArguments.drop(1).joinToString(separator = ", ") { it.text }
dotQualified.replaced(psiFactory.createExpression("$receiverText.${replacement.kotlinFunctionShortName}$typeArguments($argumentsText)"))
file.resolveImportReference(FqName(replacement.kotlinFunctionFqName)).firstOrNull()?.let {
ImportInsertHelper.getInstance(project).importDescriptor(file, it)
}
} else {
val argumentsText = valueArguments.joinToString(separator = ", ") { it.text }
val replaced = dotQualified.replaced(
psiFactory.createExpression("${replacement.kotlinFunctionFqName}$typeArguments($argumentsText)")
)
ShortenReferences.DEFAULT.process(replaced)
}
} }
} }
@@ -99,44 +66,24 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti
"Float" to "Float" "Float" to "Float"
).flatMap { (javaPrimitive, kotlinPrimitive) -> ).flatMap { (javaPrimitive, kotlinPrimitive) ->
listOf( listOf(
Replacement( Replacement("java.lang.$javaPrimitive.toString", "kotlin.text.toString", ToExtensionFunction) {
"java.lang.$javaPrimitive.toString", it.valueArguments.size == 2
"kotlin.text.toString", },
toExtensionFunction = true Replacement("java.lang.$javaPrimitive.toString", "kotlin.primitives.$kotlinPrimitive.toString", ToExtensionFunction) {
) { call -> call.valueArguments.size == 2 }, it.valueArguments.size == 1
Replacement( },
"java.lang.$javaPrimitive.toString", Replacement("java.lang.$javaPrimitive.compare", "kotlin.primitives.$kotlinPrimitive.compareTo", ToExtensionFunction)
"kotlin.primitives.$kotlinPrimitive.toString",
toExtensionFunction = true
) { call -> call.valueArguments.size == 1 },
Replacement(
"java.lang.$javaPrimitive.compare",
"kotlin.primitives.$kotlinPrimitive.compareTo",
toExtensionFunction = true
)
) )
} }
private val JAVA_IO = listOf( private val JAVA_IO = listOf(
Replacement( Replacement("java.io.PrintStream.print", "kotlin.io.print", filter = ::isJavaSystemOut),
"java.io.PrintStream.print", Replacement("java.io.PrintStream.println", "kotlin.io.println", filter = ::isJavaSystemOut)
"kotlin.io.print",
filter = ::isJavaSystemOut
),
Replacement(
"java.io.PrintStream.println",
"kotlin.io.println",
filter = ::isJavaSystemOut
)
) )
private val JAVA_SYSTEM = listOf( private val JAVA_SYSTEM = listOf(
Replacement("java.lang.System.exit", "kotlin.system.exitProcess"), Replacement("java.lang.System.exit", "kotlin.system.exitProcess"),
Replacement( Replacement("java.lang.System.arraycopy", "kotlin.collections.copyInto", ToExtensionFunction) // TODO: mapping
"java.lang.System.arraycopy",
"kotlin.collections.copyInto",
toExtensionFunction = true
) // TODO: mapping
) )
private val JAVA_MATH = listOf( private val JAVA_MATH = listOf(
@@ -152,137 +99,49 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti
Replacement("java.lang.Math.expm1", "kotlin.math.expm1"), Replacement("java.lang.Math.expm1", "kotlin.math.expm1"),
Replacement("java.lang.Math.floor", "kotlin.math.floor"), Replacement("java.lang.Math.floor", "kotlin.math.floor"),
Replacement("java.lang.Math.hypot", "kotlin.math.hypot"), Replacement("java.lang.Math.hypot", "kotlin.math.hypot"),
Replacement( Replacement("java.lang.Math.IEEEremainder", "kotlin.math.IEEErem", ToExtensionFunction),
"java.lang.Math.IEEEremainder",
"kotlin.math.IEEErem",
toExtensionFunction = true
),
Replacement("java.lang.Math.log", "kotlin.math.ln"), Replacement("java.lang.Math.log", "kotlin.math.ln"),
Replacement("java.lang.Math.log1p", "kotlin.math.ln1p"), Replacement("java.lang.Math.log1p", "kotlin.math.ln1p"),
Replacement("java.lang.Math.log10", "kotlin.math.log10"), Replacement("java.lang.Math.log10", "kotlin.math.log10"),
Replacement("java.lang.Math.max", "kotlin.math.max"), Replacement("java.lang.Math.max", "kotlin.math.max"),
Replacement( Replacement("java.lang.Math.max", "kotlin.ranges.coerceAtLeast", ToExtensionFunction),
"java.lang.Math.max",
"kotlin.ranges.coerceAtLeast",
toExtensionFunction = true
),
Replacement("java.lang.Math.min", "kotlin.math.min"), Replacement("java.lang.Math.min", "kotlin.math.min"),
Replacement( Replacement("java.lang.Math.min", "kotlin.ranges.coerceAtMost", ToExtensionFunction),
"java.lang.Math.min", Replacement("java.lang.Math.nextDown", "kotlin.math.nextDown", ToExtensionFunction),
"kotlin.ranges.coerceAtMost", Replacement("java.lang.Math.nextAfter", "kotlin.math.nextTowards", ToExtensionFunction),
toExtensionFunction = true Replacement("java.lang.Math.nextUp", "kotlin.math.nextUp", ToExtensionFunction),
), Replacement("java.lang.Math.pow", "kotlin.math.pow", ToExtensionFunction),
Replacement(
"java.lang.Math.nextDown",
"kotlin.math.nextDown",
toExtensionFunction = true
),
Replacement(
"java.lang.Math.nextAfter",
"kotlin.math.nextTowards",
toExtensionFunction = true
),
Replacement(
"java.lang.Math.nextUp",
"kotlin.math.nextUp",
toExtensionFunction = true
),
Replacement(
"java.lang.Math.pow",
"kotlin.math.pow",
toExtensionFunction = true
),
Replacement("java.lang.Math.rint", "kotlin.math.round"), Replacement("java.lang.Math.rint", "kotlin.math.round"),
Replacement( Replacement("java.lang.Math.round", "kotlin.math.roundToLong", ToExtensionFunction),
"java.lang.Math.round", Replacement("java.lang.Math.round", "kotlin.math.roundToInt", ToExtensionFunction),
"kotlin.math.roundToLong",
toExtensionFunction = true
),
Replacement(
"java.lang.Math.round",
"kotlin.math.roundToInt",
toExtensionFunction = true
),
Replacement("java.lang.Math.signum", "kotlin.math.sign"), Replacement("java.lang.Math.signum", "kotlin.math.sign"),
Replacement("java.lang.Math.sin", "kotlin.math.sin"), Replacement("java.lang.Math.sin", "kotlin.math.sin"),
Replacement("java.lang.Math.sinh", "kotlin.math.sinh"), Replacement("java.lang.Math.sinh", "kotlin.math.sinh"),
Replacement("java.lang.Math.sqrt", "kotlin.math.sqrt"), Replacement("java.lang.Math.sqrt", "kotlin.math.sqrt"),
Replacement("java.lang.Math.tan", "kotlin.math.tan"), Replacement("java.lang.Math.tan", "kotlin.math.tan"),
Replacement("java.lang.Math.tanh", "kotlin.math.tanh"), Replacement("java.lang.Math.tanh", "kotlin.math.tanh"),
Replacement( Replacement("java.lang.Math.copySign", "kotlin.math.withSign", ToExtensionFunction)
"java.lang.Math.copySign",
"kotlin.math.withSign",
toExtensionFunction = true
)
) )
private val JAVA_COLLECTIONS = listOf( private val JAVA_COLLECTIONS = listOf(
Replacement( Replacement("java.util.Arrays.copyOf", "kotlin.collections.copyOf", ToExtensionFunction) {
"java.util.Arrays.copyOf",
"kotlin.collections.copyOf",
toExtensionFunction = true
) {
it.valueArguments.size == 2 it.valueArguments.size == 2
}, },
Replacement( Replacement("java.util.Arrays.copyOfRange", "kotlin.collections.copyOfRange", ToExtensionFunction),
"java.util.Arrays.copyOfRange", Replacement("java.util.Arrays.binarySearch", "kotlin.collections.binarySearch", ToExtensionFunction), // TODO: mapping
"kotlin.collections.copyOfRange", Replacement("java.util.Arrays.equals", "kotlin.collections.contentEquals", ToExtensionFunction),
toExtensionFunction = true Replacement("java.util.Arrays.deepEquals", "kotlin.collections.contentDeepEquals", ToExtensionFunction),
), Replacement("java.util.Arrays.fill", "kotlin.collections.fill", ToExtensionFunction), // TODO: mapping
Replacement( Replacement("java.util.Arrays.sort", "kotlin.collections.sort", ToExtensionFunction) {
"java.util.Arrays.binarySearch",
"kotlin.collections.binarySearch",
toExtensionFunction = true
), // TODO: mapping
Replacement(
"java.util.Arrays.equals",
"kotlin.collections.contentEquals",
toExtensionFunction = true
),
Replacement(
"java.util.Arrays.deepEquals",
"kotlin.collections.contentDeepEquals",
toExtensionFunction = true
),
Replacement(
"java.util.Arrays.fill",
"kotlin.collections.fill",
toExtensionFunction = true
), // TODO: mapping
Replacement(
"java.util.Arrays.sort",
"kotlin.collections.sort",
toExtensionFunction = true
) {
it.valueArguments.size == 3 it.valueArguments.size == 3
}, //TODO: mapping? }, //TODO: mapping?
Replacement( Replacement("java.util.Arrays.sort", "kotlin.collections.sortWith", ToExtensionFunction) {
"java.util.Arrays.sort",
"kotlin.collections.sortWith",
toExtensionFunction = true
) {
it.valueArguments.size != 3 it.valueArguments.size != 3
}, },
Replacement( Replacement("java.util.Arrays.deepHashCode", "kotlin.collections.contentDeepHashCode", ToExtensionFunction),
"java.util.Arrays.deepHashCode", Replacement("java.util.Arrays.hashCode", "kotlin.collections.contentHashCode", ToExtensionFunction),
"kotlin.collections.contentDeepHashCode", Replacement("java.util.Arrays.deepToString", "kotlin.collections.contentDeepToString", ToExtensionFunction),
toExtensionFunction = true Replacement("java.util.Arrays.toString", "kotlin.collections.contentToString", ToExtensionFunction),
),
Replacement(
"java.util.Arrays.hashCode",
"kotlin.collections.contentHashCode",
toExtensionFunction = true
),
Replacement(
"java.util.Arrays.deepToString",
"kotlin.collections.contentDeepToString",
toExtensionFunction = true
),
Replacement(
"java.util.Arrays.toString",
"kotlin.collections.contentToString",
toExtensionFunction = true
),
Replacement("java.util.Arrays.asList", "kotlin.collections.listOf"), Replacement("java.util.Arrays.asList", "kotlin.collections.listOf"),
Replacement("java.util.Arrays.asList", "kotlin.collections.mutableListOf"), Replacement("java.util.Arrays.asList", "kotlin.collections.mutableListOf"),
Replacement("java.util.Set.of", "kotlin.collections.setOf"), Replacement("java.util.Set.of", "kotlin.collections.setOf"),
@@ -291,19 +150,15 @@ class ReplaceJavaStaticMethodWithKotlinAnalogInspection : AbstractKotlinInspecti
Replacement("java.util.List.of", "kotlin.collections.mutableListOf") Replacement("java.util.List.of", "kotlin.collections.mutableListOf")
) )
private val REPLACEMENTS = (JAVA_MATH + private val REPLACEMENTS = (JAVA_MATH + JAVA_SYSTEM + JAVA_IO + JAVA_PRIMITIVES + JAVA_COLLECTIONS)
JAVA_SYSTEM + .groupBy { it.javaMethodShortName }
JAVA_IO +
JAVA_PRIMITIVES +
JAVA_COLLECTIONS
).groupBy { it.javaMethodShortName }
} }
} }
data class Replacement( data class Replacement(
val javaMethodFqName: String, val javaMethodFqName: String,
val kotlinFunctionFqName: String, val kotlinFunctionFqName: String,
val toExtensionFunction: Boolean = false, val transformation: Transformation = WithoutAdditionalTransformation,
val filter: (KtCallExpression) -> Boolean = { true } val filter: (KtCallExpression) -> Boolean = { true }
) { ) {
private fun String.shortName() = takeLastWhile { it != '.' } private fun String.shortName() = takeLastWhile { it != '.' }
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.inspections.jdk2k
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtOperationExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
interface Transformation {
operator fun invoke(callExpression: KtCallExpression, replacement: Replacement)
fun isApplicable(call: KtCallExpression): Boolean = true
}
object WithoutAdditionalTransformation : Transformation {
override fun invoke(callExpression: KtCallExpression, replacement: Replacement) {
val psiFactory = KtPsiFactory(callExpression)
val valueArguments = callExpression.valueArguments
val typeArguments = callExpression.typeArgumentList?.text ?: ""
val argumentsText = valueArguments.joinToString(separator = ", ") { it.text }
val replaced = callExpression.getQualifiedExpressionForSelectorOrThis().replaced(
psiFactory.createExpression("${replacement.kotlinFunctionFqName}$typeArguments($argumentsText)")
)
ShortenReferences.DEFAULT.process(replaced)
}
}
object ToExtensionFunction : Transformation {
override fun invoke(callExpression: KtCallExpression, replacement: Replacement) {
val file = callExpression.containingKtFile
val psiFactory = KtPsiFactory(callExpression)
val valueArguments = callExpression.valueArguments
val typeArguments = callExpression.typeArgumentList?.text ?: ""
val receiverText = valueArguments.first().getArgumentExpression()
?.run { if (this is KtOperationExpression) "($text)" else text }
?: valueArguments.first().text
val argumentsText = valueArguments.drop(1).joinToString(separator = ", ") { it.text }
callExpression.getQualifiedExpressionForSelectorOrThis().replaced(
psiFactory.createExpression("$receiverText.${replacement.kotlinFunctionShortName}$typeArguments($argumentsText)")
)
file.resolveImportReference(FqName(replacement.kotlinFunctionFqName)).firstOrNull()?.let {
ImportInsertHelper.getInstance(callExpression.project).importDescriptor(file, it)
}
}
override fun isApplicable(call: KtCallExpression): Boolean = call.valueArguments.isNotEmpty()
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
import java.util.Arrays.hashCode
fun test() {
val a = arrayOf(1)
val hash = <caret>hashCode(a)
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
import java.util.Arrays.hashCode
fun test() {
val a = arrayOf(1)
val hash = <caret>a.contentHashCode()
}
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test() { fun test() {
<caret>System.out.print("foo") System.out.print<caret>("foo")
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test() { fun test() {
<caret>System.out.println() System.out.<caret>println()
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.IEEEremainder(x, y) Math.<caret>IEEEremainder(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.abs(x) Math.abs<caret>(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.acos(x) Math.<caret>acos(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.asin(x) Math.<caret>asin(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.atan(x) Math.<caret>atan(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.atan2(x, y) Math.<caret>atan2(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.ceil(x) Math.<caret>ceil(x)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `coerceAtLeast` function // FIX: Replace with `coerceAtLeast` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.max(x, y) Math.<caret>max(x, y)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `coerceAtMost` function // FIX: Replace with `coerceAtMost` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.min(x, y) Math.<caret>min(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.copySign(x, y) Math.<caret>copySign(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.cos(x) Math.<caret>cos(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.cosh(x) Math.<caret>cosh(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.exp(x) Math.<caret>exp(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.expm1(x) Math.<caret>expm1(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.floor(x) Math.<caret>floor(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.hypot(x, y) Math.<caret>hypot(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.log(x) Math.<caret>log(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.log10(x) Math.<caret>log10(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.log1p(x) Math.<caret>log1p(x)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `max` function // FIX: Replace with `max` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.max(x, y) Math.<caret>max(x, y)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `min` function // FIX: Replace with `min` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.min(x, y) Math.<caret>min(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.nextAfter(x, y) Math.<caret>nextAfter(x, y)
} }
@@ -1,4 +1,4 @@
// RUNTIME_WITH_FULL_JDK // RUNTIME_WITH_FULL_JDK
fun test(x: Double) { fun test(x: Double) {
<caret>Math.nextDown(x) Math.<caret>nextDown(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.nextUp(x) Math.<caret>nextUp(x)
} }
@@ -0,0 +1,5 @@
// WITH_RUNTIME
// PROBLEM: none
fun test(x: Double) {
<caret>Math.abs(x)
}
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double, y: Double) { fun test(x: Double, y: Double) {
<caret>Math.pow(x, y) Math.<caret>pow(x, y)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.rint(x) Math.<caret>rint(x)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `roundToInt` function // FIX: Replace with `roundToInt` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.round(x) Math.<caret>round(x)
} }
@@ -1,5 +1,5 @@
// FIX: Replace with `roundToLong` function // FIX: Replace with `roundToLong` function
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.round(x) Math.<caret>round(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.signum(x) Math.<caret>signum(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.sin(x) Math.<caret>sin(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.sinh(x) Math.<caret>sinh(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.sqrt(x) Math.<caret>sqrt(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.tan(x) Math.<caret>tan(x)
} }
@@ -1,5 +1,5 @@
// WITH_RUNTIME // WITH_RUNTIME
// WITH_RUNTIME // WITH_RUNTIME
fun test(x: Double) { fun test(x: Double) {
<caret>Math.tanh(x) Math.<caret>tanh(x)
} }
@@ -1,4 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
fun test() { fun test() {
<caret>System.exit(0) System.exit<caret>(0)
} }
@@ -2,5 +2,5 @@
fun foo() { fun foo() {
val b = listOf(42, 10) val b = listOf(42, 10)
println(Integer<caret>.toString(b.first(), b.last()).let{it} + 1) println(Integer.<caret>toString(b.first(), b.last()).let{it} + 1)
} }
@@ -1,5 +1,5 @@
// WITH_RUNTIME // WITH_RUNTIME
fun foo() { fun foo() {
Integer<caret>.toString(42 + 24, 16) Integer.<caret>toString(42 + 24, 16)
} }
@@ -9106,6 +9106,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/collections/hashCode.kt"); runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/collections/hashCode.kt");
} }
@TestMetadata("hashCodeWithImport.kt")
public void testHashCodeWithImport() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/collections/hashCodeWithImport.kt");
}
@TestMetadata("mutableListOf.kt") @TestMetadata("mutableListOf.kt")
public void testMutableListOf() throws Exception { public void testMutableListOf() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/collections/mutableListOf.kt"); runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/collections/mutableListOf.kt");
@@ -9365,6 +9370,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/math/nextUp.kt"); runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/math/nextUp.kt");
} }
@TestMetadata("notApplicableAbs.kt")
public void testNotApplicableAbs() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/math/notApplicableAbs.kt");
}
@TestMetadata("pow.kt") @TestMetadata("pow.kt")
public void testPow() throws Exception { public void testPow() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/math/pow.kt"); runTest("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog/math/pow.kt");