Kotlin JUnit Rules - kotlin

In Kotlin M13, this was an acceptable way to create a JUnit rule:
#Rule #publicField val temp = TemporaryFolder()
Now that #publicField has been deprecated, how else can this be achieved? The IDE hint suggests replacing #publicField with lateinit, but lateinit val's are no longer allowed, and I'm not sure this would help even if they were.

The answer as of Kotlin 1.0 is as follows:
#Rule #JvmField val temp = TemporaryFolder()
#JvmField exposes the backing field with the same visibility as the property, ergo a public field for the JUnit rule to use.

If anyone stumble's on this. I believe the approach with JJunit5 would be using #TempDir.
https://junit.org/junit5/docs/5.4.2/api/org/junit/jupiter/api/io/TempDir.html
If you would need share the TempDir with tests, it must be a static property of the class. Static for java or within a companion Object for Kotlin

Just guessing, but the following might work (with var):
#Rule lateinit var temp = TemporaryFolder()
I would try asking at kotlin's slack http://t.co/xpQXUKaDvP
Currently it's the fastest way to fix anything.

Related

Using kotlin expression annotations

Kotlin allows to annotate expressions. It is however unclear, how such annotations may be useful and how to use them.
Let's say in following example I would like to check, that string contains number specified in #MyExpr annotation. Can this be achieved and how?
#Target(AnnotationTarget.EXPRESSION)
#Retention(AnnotationRetention.SOURCE)
annotation class MyExpr(val i: Int) {}
fun someFn() {
val a = #MyExpr(1) "value#1";
val b = #MyExpr(2) "value#2";
}
Specifying #Target(AnnotationTarget.EXPRESSION) is just a way of telling the compiler where the user of the annotation can put it.
It does not do anything on it's own rather than that.
So e.g.
#Target(AnnotationTarget.EXPRESSION)
#Retention(AnnotationRetention.SOURCE)
annotation class Something
// compiler will fail here:
#Something class Foo {
// but will succeed here:
val a = #Something "value#1"
}
Unless you're writing an Annotation Processor (so a thing that looks for Annotations and does something with them), your annotations have just informational value. They are just a signal to other devs (or future You) of something.
#Target(AnnotationTarget.EXPRESSION)
#Retention(AnnotationRetention.SOURCE)
annotation class UglyAndOldCode
val a = #UglyAndOldCode "this is something old and requires refactoring"
If you want to implement what you've stated in your question you would have to create an Annotation Processor that checks expressions marked with MyExpr for the condition that you've specified.

Utils class in Kotlin

In Java, we can create an utilities class like this:
final class Utils {
public static boolean foo() {
return false;
}
}
But how to do this in Kotlin?
I try using functions inside object:
object Utils {
fun foo(): Boolean {
return false
}
}
But when call this method from Java code it need to add INSTANCE. Ex: Utils.INSTANCE.foo().
Then I change to declare it as top-level function (without class or object):
#file:JvmName("Utils")
#file:JvmMultifileClass
fun foo(): Boolean {
return true
}
Then I can call Utils.foo() from Java code. But from Kotlin code I got Unresolved reference compiler error. It only allow be to use foo() function directly (without Utils prefix).
So what is the best approach for declaring utils class in Kotlin?
The last solution you've proposed is actually quite idiomatic in Kotlin - there's no need to scope your function inside anything, top level functions are just fine to use for utilities, in fact, that's what most of the standard library consists of.
You've used the #JvmName annotation the right way too, that's exactly how you're supposed to make these top level functions easily callable for Java users.
Note that you only need #JvmMultifileClass if you are putting your top level functions in different files but still want them to end up grouped in the same class file (again, only for Java users). If you only have one file, or you're giving different names per file, you don't need this annotation.
If for some reason you want the same Utils.foo() syntax in both Java and Kotlin, the solution with an object and then #JvmStatic per method is the way to do that, as already shown by #marianosimone in this answer.
You'd need to use #JvmStatic for that:
In Kotlin:
object Utils {
#JvmStatic
fun foo(): Boolean = true
}
val test = Utils.foo()
In Java:
final boolean test = Utils.foo()
Note that the util class you used in Java was the only way to supply additional functions there, for anything that did not belong to a particular type or object. Using object for that in Kotlin does not make any sense. It isn't a singleton, right?
The second approach you mentioned is rather the way to go for utility functions. Internally such functions get translated to static ones and as you can see they become the static util classes in Java you are searching for, as you can't have standalone functions in Java without a class or enum. In Kotlin itself however they are just functions.
Some even count utility classes to the anti-patterns. Functions on the other hand make totally sense without a class or object whose name hasn't so much meaning anyway.

What's Kotlin equivalent of Class<?>

I want a map between Int and any class. In Java it would be Map<Class<?>, Integer>. What's the Kotlin equivalent of that?
KClass is Kotlin's equivalent to java.lang.Class.
An instance of KClass can be obtained with ::class on either a type or a value (i.e. String::class, 3.8::class).
If you require a Java Class instance from a KClass you can use the java extension property:
val kotlinClass: KClass<String> = String::class
val javaClass: Class<String> = String::class.java
Keep in mind that if you want to use kotlin-reflect's full features you will need kotlin-reflect on the classpath.
So in your case, the equivalent would be Map<KClass<*>, Int>.
The equivalent declaration would be Map<Class<*>, Int>.
You're looking for KClass. You need to add the Kotlin reflection library in order to use it.

Using lateinit primitives wrappers

I've got something like that:
#LocalServerPort
private lateinit var serverPort: Integer
And IDEA warns that java.lang.Integer should not be used, use kotlin.Int instead. But kotlin.Int cannot be used with a lateinit property. Is there a way to satisfy both restrictions?
Update: I'm compiling with -Werror, as I think every project should. Therefore, code becomes ridden with #Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") adding unnecessary garbage.
Yes there is, Delegates.
#LocalServerPort
private var serverPort by Delegates.notNull<Int>()
Delegates are computationally slightly more expensive than lateinit. I use lateinit where I can, otherwise I use the method above. The code above will present exactly the same as lateinit ie. no null check needed.

Kotlin-allopen plugin + #JvmField on a val not final enough

I am testing a new kotlin-allopen and kotlin-spring plugins under Kotlin 1.0.6.
In one of my #Transactional-annotated classes I have a field:
#JvmField val foo = null
When I try to build the project, I get:
Error:(45, 5) Kotlin: JvmField can only be applied to final property
Is there any proper way of dealing with this? My real-life code needed #JvmField because of the JUnit's #Rule. Managed to "solve" the problem by removing a #JvmField and annotating a getter instead. Not sure if a bug or a feature.
I got the official solution.
In such case, finality provided by val is not enough. It turns out you need explicitly add final keyword there and this is not considered a bug.
#JvmField final val foo = null