I use next version of junit 5
<junit.jupiter.version>5.2.0</junit.jupiter.version>
<junit.platform.version>1.2.0</junit.platform.version>
<junit.vintage.version>5.2.0</junit.vintage.version>
Kotlin version is
<kotlin.version>1.2.31</kotlin.version>
I try to use new assertion functionality from junit 5 with kotlin like
assertAll("person",
{ assertEquals("John", person.firstName) },
{ assertEquals("Doe", person.lastName) }
)
but code analyzer says that no suitable version of the method is found.
Error:(28, 9) Kotlin: None of the following functions can be called with the arguments supplied:
public fun assertAll(vararg executables: () -> Unit): Unit defined in org.junit.jupiter.api
public fun assertAll(heading: String?, vararg executables: () -> Unit): Unit defined in org.junit.jupiter.api
if I write the code like this it works fine. What is the trick?
assertAll("person",
Executable { assertEquals("John", person.firstName) },
Executable { assertEquals("Doe", person.lastName) }
)
Use the Kotlin function assertAll() and not the static function Assertions.assertAll() and you will be happy. Change your import from:
import org.junit.jupiter.api.Assertions.assertAll
to:
import org.junit.jupiter.api.assertAll
And now this code will work:
assertAll("person",
{ assertEquals("John", person.firstName) },
{ assertEquals("Doe", person.lastName) }
)
You would be interested to know that JUnit 5 includes Kotlin helpers within its main source code, directly from the JUnit team!
If you really, really, really want to use the straight Java version, you need to type your Lambda:
assertAll("person",
Executable { assertEquals("John", person.firstName) },
Executable { assertEquals("Doe", person.lastName) }
)
Related
I'm using kotlin compiler to analyze kotlin source file and I need to get where the method is defined using KtCallExpression.
KtCallExpression in question is retrieved from method call.
For better explanation, here's example, if there's source file named Main.kt with contents:
fun main() {
f1()
Test.f2()
}
fun f1() {
}
class Test {
companion object {
fun f2() {
}
}
}
when analyzing function main, it will produce 2 KtCallExpression, one for f1() and other for f2()
However I'm not sure how to get file Main.kt from KtCallExpression for f1(), or class Test from KtCallExpression for f2()
I tried to look for its documentations, however Kotlin compiler doesn't contain enough docs. I've also tried bunch of auto completion suggested by Intellij Idea but none of those doesn't seem to lead me to original declaration.
Goal
I would like to globally disable inlining of #JvmInline value class classes via a compiler flag or something similar. I would want to do this when running unit tests but not in production.
Motivation
I would like to use mockk with value classes.
I want to write a unit test that looks like this:
#JvmInline
value class Example(private val inner: Int)
class ExampleProvider {
fun getExample(): Example = TODO()
}
#Test
fun testMethod() {
val mockExample = mockk<Example>()
val mockProvider = mockk<ExampleProvider> {
every { getExample() } returns mockExample
}
Assert.assertEquals(mockExample, mockProvider.getExample())
}
This code fails with the following exception:
no answer found for: Example(#4).unbox-impl()
I think that if I were able to disable class inlining that this would no longer be an issue.
Suppose we have the following functions:
class MyClass {
fun myFunction() {}
companion object {
fun myStaticFunction() {}
}
}
fun myTopLevelFunction() {}
When I am debugging thru the following:
val functions = listOf(
MyClass::myFunction,
MyClass.Companion::myStaticFunction,
::myTopLevelFunction
)
functions.forEach {
val names = (it::class.java).fields.map {
method -> println(method.name)
}
Intellij can correctly show me in "Evaluate Expression" this information
owner (MyClass, MyClass.Companion etc.
whether this is a top level function
But I cannot find a way to do it via reflection. For instance, I cannot figure out how to read function's owner. What am I missing? TIA.
In Intellij I can see functions' owners like this
myFunction -> MyClass
myStaticFunction -> MyClass.Companion
myTopLevelFunction -> MyFileNameKt
I believe KFunction does not provide us with such capability. If you are not afraid of using publicly available utils from kotlin.jvm.internal package then you can check if KFunction is a CallableReference and then use its owner property:
functions.forEach {
if (it is CallableReference) {
println(it.owner)
}
}
Suppose a Library's method takes a callback handler Handler, but for handling the result, the same logic is used over and over again. So, I created a class SimpleHandler that has the logic. The users that use that class are suppose to override its methods onSuccess onFail, if necessary. But if the handling is not necessary for the specific case, the user may not override them, and the SimpleHandler's default handler will be used.
The problem is that when I auto-complete the methods, the IDE automatically inserts super calls, like super.onFail(). For this code, as you see below, if it is overridden, the super method should not be called. Is there any way to mark that the super method should not be called when overridden, so the IDE will stop inserting it?
interface Handler
{
fun onFinished(result:Int);
}
abstract class SimpleHandler:Handler
{
override fun onFinished(result: Int)
{
if(result==0)
{
onSuccess();
}
else
{
onFail();
}
}
open fun onSuccess()
{
println("The developer is so lazy that he did not do anything.");
}
open fun onFail()
{
println("The developer is so lazy that he did not do anything.");
}
}
fun doSomething(handler:Handler)
{
handler.onFinished(10);
}
fun main(args: Array<String>)
{
doSomething(object: SimpleHandler(){
override fun onSuccess() {
println("I won! I won!");
}
override fun onFail() {
//super.onFail();
println("Me fail English?");
}
})
}
In IDEA/Android Studio, this is governed by Editor > File and Code Templates under Settings.
On my installation, I see Overridden Method Body and Overridden Scala Method Body but no special template for Kotlin. So I would expect Kotlin to be using the Java template.
You can change this template not to call super for a given method name, but it looks like you don't have access to the supertype's name. See the linked documentation for how templates can be shared.
AFAIK, there is no problem in writing something like this:
fun doSomething(handler:Handler, result: Int) {
handler.onFinished(result)
}
fun main() {
doSomething(object: SimpleHandler() {
override fun onFail() {
println("My custom message")
}
}, 10)
}
fun main2() {
doSomething(object : SimpleHandler() {
override fun onSuccess() {
println("My other custom message")
}
}, 0)
}
The developer only needs to override, if needed, the callback he's interested in.
In this case, in main() fails, it'll print "my custom message". If it succeeds, the default onSuccess() will be called.
The reverse is also true for main2(): If it succeeds, it'll print "My other custom message", but it it fails, it'll simply call the default onSuccess.
Tested on AS 3.1.1 with org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.31
You would need to define a separate lint detector for that.
Lint highlights overrides which should call super, but don't, by use of #CallSuper annotation, which is what this Lint detector enables:
https://cs.android.com/android/platform/superproject/+/master:tools/base/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CallSuperDetector.java
Granted that might be something new to learn first, but writing custom Lint rules is not that hard. These are some good starting points:
Android Lint Tool Guide https://developer.android.com/studio/write/lint.html
2017 Kotlin Conference Lint Talk
https://www.youtube.com/watch?v=p8yX5-lPS6o
The last time I used Kotlin was Dec 2015 when I used it to solve a couple of Project Euler problems.
This time I want to try its interoperability with Javascript. Now my question is, how do we import/use existing Javascript libraries in Kotlin?
I've seen some people using the native keyword, and I just want a brief explanation of it.
There's no native keyword anymore, there's #native annotation. Currently, it's working solution and you can use it with 1.0.x branch of Kotlin compiler. However, we are going do deprecate this annotation in favour of extern annotations, so be prepared to rewrite your code eventually for 1.1.x branch.
When you put #native annotation on a class or on a top-level function, two things happen:
Its body is not compiled to JavaScript.
Compiler references this class or function directly, without package name and mangling.
I think it's easier to explain by providing example of a JavaScript library:
function A(x) {
this.x = x;
this.y = 0;
}
A.prototype.foo = function(z) {
return this.x + this.y + z;
}
function min(a, b) {
return a < b ? a : b;
}
and a corresponding Kotlin declaration
#native class A(val x: Int) {
var y: Int = noImpl
fun foo(z: Int): Int = noImpl
}
#native fun min(a: Int, b: Int): Int = noImpl
Note that noImpl is a special placeholder that's required because of non-abstract functions required bodies and non-abstract properties require initializers. BTW, when we replace #native with extern, we'll get rid of this noImpl.
Another aspect of interoperation with JS libraries is including libraries via module system. Sorry, we don't have any solution right now (but are going to release it soon). See proposal. You can use the following workaround for node.js/CommonJS:
#native interface ExternalModule {
fun foo(x: Int)
}
#native fun require(name: String): dynamic = noImpl
fun main(args: Array<String>) {
val module: ExternalModule = require("externalModule")
module.foo(123)
}
where external module is declared like this
function foo(x) {
return x + 1;
}
module.exports = { foo : foo };
I added a simple barebone project as an example of how to do Kotlin2Js.
https://bitbucket.org/mantis78/gradle4kotlin2js/src
Here is the gradle file that is the main recipe.
group 'org.boonhighendtech'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.2-5'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
build {
outputs.dir("web/")
}
build.doLast {
copy {
from 'src/main/webapp'
into 'web/'
include '**/*.html'
include '**/*.js'
include '**/*.jpg'
include '**/*.png'
}
configurations.compile.each { File file ->
copy {
includeEmptyDirs = false
from zipTree(file.absolutePath)
into "${projectDir}/web"
include { fileTreeElement ->
def path = fileTreeElement.path
path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
}
}
}
}
clean.doLast {
file(new File(projectDir, "/web")).deleteDir()
}
compileKotlin2Js {
kotlinOptions.outputFile = "${projectDir}/web/output.js"
kotlinOptions.moduleKind = "amd"
kotlinOptions.sourceMap = true
}
Firstly, you can assign a dynamic variable then essentially code it like you code JavaScript, dynamically.
e.g.
val jQuery: dynamic = passedInJQueryRef
jQuery.whateverFunc()
But if your intention is to have it typed, then you need to introduce types to the external library. One way is to make use of the relatively extensive libraries of typedefs by https://github.com/DefinitelyTyped/DefinitelyTyped
Find the ts.d there, then run ts2kt (https://github.com/Kotlin/ts2kt) to get your Kotlin files. That typically gets you there. Occasionally, certain conversions are not well done. You will have to hand fix the conversion. E.g. snapsvg's snapsvg.attr() call takes in "{}" but it got converted to some strange interface.
It was
fun attr(params: `ts$2`): Snap.Element
And I replaced it with
fun attr(params: Json): Snap.Element
and it works like a charm.
Kotlin 1.1 introduces the externalmodifier that can be used to declare functions and classes written directly in JS, see http://kotlinlang.org/docs/reference/js-interop.html