Kotlin: Kotlin-script (.kts) cannot use regular code? - kotlin

In my library's codebase, I have this package function: fun sayHello() = println("Hello there!")
The function is defined in the package org.jire.pomade
I would like to use this function in a .kts file like so: sayHello()
Unfortunately I can't seem to get code apart from Kotlin's own stdlib to work in Kotlin-script files.
The entirety of my script:
import org.jire.pomade.sayHello
sayHello()
The result of running the script:
pomade.kts:1:12: error: unresolved reference: jire
import org.jire.pomade.sayHello
^
pomade.kts:3:1: error: unresolved reference: sayHello
sayHello()
^
Anybody know why this is happening? Thanks.

This is a bug in the Kotlin plugin: https://youtrack.jetbrains.com/issue/KT-11618

I suggest to use holgerbrandl/kscript to manage dependencies of your script.

There is experimental support for maven imports in Kotlin scripts since 1.3.
Take a look at https://blog.jetbrains.com/kotlin/2018/09/kotlin-1-3-rc-is-here-migrate-your-coroutines/#scripting:
#file:Repository("https://jcenter.bintray.com")
#file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.11")
import kotlinx.html.*
import kotlinx.html.stream.*
print(createHTML().html {
body {
h1 { +"Hello, World!" }
}
})
And here is the KEEP: https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md.

Alternative is using the Kotlin REPL instead.

Related

Unresolved reference Math in InteliJ IDEA Kotlin

I have this code, it works, but compiler InteliJ IDEA doesn't see Math package and it's methods.
It defines Math like unresolved reference and propose to create class "Math". How to solve this problem?
import kotlin.math.*
fun main() {
println(five("rain"))
}
fun five(a: String) = a.substring(0, Math.min(5, a.length))
Just remove the Math. part. So like
fun five(a: String) = a.substring(0, min(5, a.length))
The import makes the min function available just like that. Don't need to write Math. in front of it

How to bind i18next-browser-languagedetector to Kotlin?

The Gradle project is set by the JS plugin:
plugins {
kotlin("js") version("1.6.10")
}
and uses the LEGACY compilation backend:
kotlin {
js(LEGACY) {
// ...
}
}
My goal is to use the following dependencies in Kotlin sources:
dependencies {
implementation(npm("i18next", "21.6.11"))
implementation(npm("react-i18next", "11.15.4"))
implementation(npm("i18next-browser-languagedetector", "6.1.3"))
}
It was pretty easy to describe JS-Kotlin bridging for the first two dependencies:
#JsModule("i18next")
#JsNonModule
external val i18next: I18n
external interface I18n {
fun use(module: dynamic): I18n
}
#JsModule("react-i18next")
#JsNonModule
external val reactI18next: ReactI18next
external interface ReactI18next {
val initReactI18next: dynamic
}
Unfortunately, the last one - i18next-browser-languagedetector - is driving me some nuts with its configuration. Something like this:
#JsModule("i18next-browser-languagedetector")
#JsNonModule
external val LanguageDetector: dynamic
doesn't work - the actual LanguageDetector provided by the declaration above is {}, so i18next doesn't consume it in Kotlin code (the JS code throws You are passing a wrong module! Please check the object you are passing to i18next.use()):
i18next.use(LanguageDetector) // fails
Can anyone please help me with a declaration of a JS-Kotlin bridge for the LanguageDetector?
Well, by debugging a little bit I've managed to solve this JS-Kotlin bridging issue. The working solution is the following declaration:
#JsModule("i18next-browser-languagedetector")
#JsNonModule
external val i18nextBrowserLanguageDetector: I18nextBrowserLanguageDetector
external interface I18nextBrowserLanguageDetector {
#JsName("default")
val LanguageDetector: dynamic
}
Now it's possible to do first parts of the i18next initialization chain:
i18next
.use(i18nextBrowserLanguageDetector.LanguageDetector)
.use(reactI18next.initReactI18next)
// ...
Unfortunately, it's difficult to say that I'm getting any intuition behind it (maybe because of my huge blind spots in JS) - so any additional clarification or explanations would be helpful still.
My biggest concern is that LanguageDetector from the declaration above should be a class, but it seems like no way to use something else rather than dynamic property. When I try to lift up the #JsName("default") annotation to mark some class protocol with it, it doesn't compile:
#JsModule("i18next-browser-languagedetector")
#JsNonModule
#JsName("default")
external class LanguageDetector
It's not possible to use a nested class inside of the interface as well in this case:
#JsModule("i18next-browser-languagedetector")
#JsNonModule
external interface I18nextBrowserLanguageDetector {
#JsName("default")
class LanguageDetector
}
So while it seems to be solved, it's super-frustrating still.

Create a Gradle function for dependencies block in Kotlin

Currently, I'm creating a function, which is available for the dependencies block in Groovy with:
project.dependencies.ext.foo = { String value ->
project.files(extension.getFooDependency(project).jarFiles).asFileTree
}
Thanks to that, I'm able to do:
afterEvaluate {
dependencies {
compileOnly foo('junit')
}
}
I'm converting the Groovy code to Kotlin, and I'm wondering how to rewrite this foo extension.
I've ended up with:
project.dependencies.extensions.extraProperties.set("foo", Action { value: String ->
project.files(extension.getIdeaDependency(project).jarFiles).asFileTree
})
After calling foo('junit'), I get the following exception:
> Could not find method foo() for arguments [junit] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
I do not think that would work the same way in Kotlin DSL. Instead, you may declare a Kotlin extension function somewhere in the project. Then calling it would include all necessary receivers to you.
For multiple projects, I would recommend using a buildSrc project. Declarations there are visible to all project files below.
Speaking about Groovy and Kotlin support, I would do something like that:
private fun getFooImpl(scope: getFooImpl, name: String) { /*here is the implementation */ }
fun DependencyHandlerScope.getFoo(name:String) = getFooImpl(this, name)
//in Groovy
project.dependencies.extensions.extraProperties.set("foo", {getFooImpl(..)})
The same code could fit into a plugin as well. A more generic way could be to register a custom DLS extension, so to allow a custom block-like thisIsMyPlugin { .. } in the Gradle DSL and define all necessary helper functions in the extension class. Here the downside is in forcing users to wrap their code into the thisIsMyPlugin block.

what's the difference between kotlin main functions

what's the difference between this two types of main function in kotlin
fun main(args: Array<String>) {
print("Hello World!")
}
and
fun main() {
print("Hello World!")
}
The syntax with the args is used to pass the parameters to the module from command line interface or from outside program. If you don't need it, you can omit it.
If you are getting started with kotlin I strongly recommend you to look at kotlin official website.
With the first option you could pass arguments when running your program

Error:(1, 41) Kotlin: Symbol is declared in module 'jdk.internal.opt' which does not export package 'jdk.i

I have a beginner problem.
Just installed IntellijIDEA and JDK (Java Development Kit) and can't build my project.
Code:
import jdk.internal.joptsimple.internal.Strings
fun main(args: Array<Strings>){println("Hello")}
Error:
Error:(1, 41) Kotlin: Symbol is declared in module 'jdk.internal.opt' which does not export package 'jdk.internal.joptsimple.internal'
The proper main function with arguments looks like this:
fun main(args: Array<String>) {
}
Note that args is an array of Kotlin's String not jdk.internal.joptsimple.internal.Strings. So just fix your method's signature and remove the import statement.