Java to Kotlin Tool - Conversion errors


#1

I’m looking into using Kotlin with Spring Cloud. To this end I looked at the Spring Cloud blog post:

And checked out the code from:

After I got it up and running in Java I used the built-in J2K conversion tool in IntelliJ to convert all classes at once into Kotlin.

I tried both Kotlin 1.0.4 and 1.0.5-eap-66.

The resuling code had a number of errors. Some errors due to classes being final by default and Spring (GCLIB) liking them to be open - this is a known issue, and being worked on. However, some of the classes were converted as ‘object’ instead of ‘class’ and containing a main() method, so a bit of extra typing was required to make a companion object and add @JvmStatic annotation.
Inconvenient, but required due to specifics of Spring Annotations - nothing the conversion tool could know about.

More serious is a number of compilation errors. These are partly to do with getter/setter methods for properties: there’s a getter method on the ‘balance’ property which is not converted correctly resulting in an error:

class Account : Serializable {
    protected var balance: BigDecimal

  ...
    fun getBalance(): BigDecimal {
        return balance.setScale(2, BigDecimal.ROUND_HALF_EVEN)
    }

}

(Happens in 2 places)

Several properties are missing a lateinit modifier:

class Account : Serializable {
    var number: String
        protected set
}

Resulting again in syntax errors

Another source of errors was some confusion with nullable types after conversion. Deduction of what can be null and what cannot be, seems to have some inconsistencies.
One example of an error is:

class Account : Serializable {
    companion object {

        private const val serialVersionUID = 1L

        var nextId: Long? = 0L

        /**
         * This is a very simple, and non-scalable solution to generating unique
         * ids. Not recommended for a real application. Consider using the
         * <tt>@GeneratedValue</tt> annotation and a sequence to generate ids.

         * @return The next available id.
         */
        protected fun getNextId(): Long? {
            synchronized(nextId) {
                return nextId++
            }
        }
    }

}

This generates multiple syntax errors due to shadowing of property and getter, but also because the property is defined as Long? type instead of Long, despite it having a value assigned in the declaration, and then the ++ operation decides to error since it cannot directly operate on a nullable type.

I eventually rewrote this to:

class Account : Serializable {
    ...
    companion object {

        private val serialVersionUID = 1L

        /**
         * This is a very simple, and non-scalable solution to generating unique
         * ids. Not recommended for a real application. Consider using the
         * @GeneratedValue annotation and a sequence to generate ids.

         * @return The next available id.
         */
        var nextId: Long = 0L
            get() = synchronized(field) { field++ }
    }
}

I’m wondering - should I raise a single issue for these conversion errors, or should I raise an issue for each error which I encountered?


#2

It’s better to raise separate issues for each problematic situation. Note that it’s not always possible for the conversion tool to understand what the best Kotlin solution would be, and we believe that it’s more useful to sometimes leave red code for the user to convert to the best possible Kotlin solution than to leave compilable code that will not actually do the right thing.