I have the following methods:
fun RowVector(x: Double, y: Double): RowVector2 = RowVector(listOf(x, y)) as RowVector2
fun RowVector(x: Double, y: Double, z: Double): RowVector3 = RowVector(listOf(x, y, z)) as RowVector3
fun RowVector(vararg elements: Double): RowVector = RowVector(elements.asList())
fun RowVector(elements: List<Double>): RowVector = // Actually creates the RowVector instance
While there are some legitimate use-cases to call RowVector(elements: List<Double>), I would like to encourage callers to use the vararg version of the method, as this allows the compiler to do some smarter type inference, like here:
val vector1 = RowVector(listOf(0.0, 1.0, 2.0)) // Type is inferred to be RowVector
val vector2 = RowVector(0.0, 1.0, 2.0) // Compiler can see that only 3 values are passed and therefore infers RowVector3
I am therefore adding a @Deprecated annotation to RowVector(elements: List<Double>) which suggests the caller to rather use the vararg version, but can easily be suppressed if the use-case is actually legitimate.
The issue that I am facing is with the design of the ReplaceWith part of the @Deprecated annotation. I would like the IDE to replace RowVector(listOf(0.0, 1.0, 2.0)) with RowVector(0.0, 1.0, 2.0), but so far, I have not found a way to do that:
@Deprecated(
"Prefer the vararg interface if possible as it allows the compiler to infer types better.",
ReplaceWith("RowVector(*elements.toDoubleArray())")
)
leads to RowVector(*listOf(0.0, 1.0, 2.0).toDoubleArray()), which still requires manual clean-up.
@Deprecated(
"Prefer the vararg interface if possible as it allows the compiler to infer types better.",
ReplaceWith("RowVector(*doubleArrayOf(elements))")
)
weirdly does nothing and
@Deprecated(
"Prefer the vararg interface if possible as it allows the compiler to infer types better.",
ReplaceWith("RowVector(*elements)")
)
does a literal replacement like so: RowVector(*listOf(0.0, 1.0, 2.0)).
I know that this is a first-world problem and that the caller can just read the warning and remove the listOf() quite easily, but I would nevertheless try to make it as easy as possible for the caller.
Most likely this is just not possible, sadly.
In your example, you declare the
List<Double>directly inside the function call. However, this is not the only way to call the function.For example, I could declare the
Listinside avalue first.In case you were able to declare a replacement using
ReplaceWiththat would extract the values from theListprovided, the IDE effectively would need to inline the declaration, possibly altering behaviour.In addition, the
Listcould be the result of a function call, which would make a automatic replacement even more problematic.As the outcome of this code is (nearly) random, I don't see how a replacement could work here.
Personally, I would just leave out the
ReplaceWithentirely in this case and rather provide a goodmessagewith clues on how to properly change the code manually.