Running Kotlin Scripts (.kts) with bindings from IntelliJ - unresolved reference: bindings - kotlin

I am trying to run .kts scripts (using Script Engine) from a Kotlin program.
The Kotlin scripts reside in the resource folder of the project and normally they have support for auto-completion, IDE checks, auto-complete, etc.
The problem appeared when I wanted to pass external variables to the script using bindings. I am doing something like:
scriptEngine.eval(scriptContent, scriptEngine.createBindings().apply { putAll(bindings) })
The bindings is a Map<String, Any> that contains the variables I want to access in my script: bindings["variable"].
Problem is that IntellIJ doesn't recognize bindings in the .kts script, so it shows a "unresolved reference: bindings". If I run the script from command line everything is fine, but inside IntelliJ i have this problem.
Is there a way to overcome the issue ? Has any experienced the same problem?

Related

Execute .kts (kotlin script) from gradle

Scenario:
A gradle project, using the org.jetbrains.kotlin.jvm plugin
The project has some *.kts kotlin script files located inside src/main/kotlin. The scripts do various tasks, for instance there is a script for loading test data from a set of CSV files into a local H2 database, a script for creating a test user in the database etc.
I currently run these scripts using IntelliJ IDEA run configurations
The gradle build file is using kotlinscript (build.gradle.kts)
To make things easier to set up for new developers, I would like to configure gradle so I can run the scripts directly using gradle. That would simplify my README.md, instead of "use IntelliJ to execute the script xxx.kts with arguments yyy and zzz, then nnn.kts", I could write "execute gradle loadTestDataIntoLocalH2Database".
Questions/issues:
Is there a simple way to execute a *.kts script from gradle?
Puzzled my answer together from https://docs.gradle.org/current/userguide/plugins.html#sec:script_plugins , https://kotlinexpertise.com/execute-kotlin-scripts-with-gradle/ and https://stackoverflow.com/a/52139585/9936828
Although I didn't try it, the second link seems like the best solution if you are ok with adding the scripts to your projects package instead of keeping them as loose scripts.
Tested with gradle 7.2.
First option is the most straightforward with no changes to code, but requires you to install the kotlin compiler CLI (kotlinc), gradle can then call it to execute the scripts:
task<Exec>("MyTask") {
commandLine("kotlinc", "-script", "foo.gradle.kts")
}
Then call it with gradle -q MyTask. Or obviously you could also provide the direct instructions to run kotlinc for the user without wrapping it in gradle.
Second option would be to load your script as a plugin. This however causes the kotlinscript annotations such as external imports (#file:Import, etc) to not work.
Wrap your code in your script in a task:
tasks.create("MyTask") {
doLast {
<do your stuff here>
}
}
load as plugin in your build script:
apply(from = "foo.kts")
Then call it with gradle -q MyTask.

Why aren't "internal" types in the main source tree visible in my unit tests?

I've got a Kotlin project in IntelliJ that is structured like this:
main/com/foo/Bar.kt
test/com/foo/BarTest.kt
where Bar is defined as:
internal class Bar
and BarTest is something like:
class BarTest {
private lateinit var bar: Bar
}
I'm getting compiler errors in IntelliJ on the reference to Bar with the message:
Cannot access 'Bar': it is internal in 'com.foo'
The tests, however, compile and run from the command line (via Gradle).
How can I suppress/remove this error when using IntelliJ?
My setup is:
macOS 10.14.1
IntelliJ 2018.2.6
Kotlin 1.3.10
I opened up two projects concurrently using the same IntelliJ installation:
a former project in which I was able to unit test an internal class located in the main source tree (all within the boundaries of the same IntelliJ module)
the current project in which I was unable to reproduce this setup
The fact that IntelliJ still gave no errors in the former setup led me to conclude the issue was not to do with my IntelliJ setup. As #JaysonMinard suggested, I looked at the differences in the Gradle configuration.
The difference was in the current project's top-level settings.gradle, I use the convention of renaming modules, a la:
findProject(':module-blah')?.name = 'blah'
...so as to refer to my Gradle projects by shorter names while having them listed contiguously in my project browser (rather than being scattered around with other files alphabetically). Removing this shortcut restored the behavior I was looking for in my unit tests.

Is there any way to reuse IntelliJ ui components such as com.intellij.ui.components.JBScrollPane?

When calling new JScrollPane, I was prompted to use a JBScrollPane.
com.intellij.ui.components.JBScrollPane
But when I do import com.intellij.ui.components.JBScrollPane, the compilation triggered an error.
error: cannot find symbol
import com.intellij.ui.components.JBScrollPane;
I tried adding this repository artifact, but it doesn't work.
This inspection is supposed to be shown only in the code of IntelliJ itself and IntelliJ plugins; if you saw it in a regular Swing project, it's a bug.
IntelliJ components can be adapted to be used outside of IntelliJ, but they are not packaged and published in a way that makes it easy.

Accessing libraries in IntelliJ GDSL script

I have a Groovy DSL script which uses classes from libraries, for example org.joda.time.LocalDateTime.
In the actual Groovy DSL script I don't have the import to the class, it's added later when executing the script.
I wrote a GDSL script for code completion in IntelliJ, but IntelliJ doesn't recognize LocalDateTime class in my script.
When I try to do an import to that class in the GDSL script, I get an error saying that the class cannot be resolved, even though it's on the project's classpath, cause when I run the project's tests for example, it works.
How can I make IntelliJ see classes from external libraries in my DSL script using GDSL script?

Can't replicate simple akka project in intelliJ

I am a new scala user and am having problems getting a development environment functional.
I downloaded the typesafe activator which launches an editor in a web browser and was able to run the akka actor tutorial script fine.
However, I have set up my intelliJ scala/akka environment, and when copying the same sample code to intelliJ, I am getting compile errors. I have added akka 2.2-M1 via maven to my project.
Initially when I copy
import akka.actor.{ActorSystem, Props, Actor, Inbox}
the last "Inbox" library is highlighted in red, and on compile I get "Error: object Inbox is not a member of package akka.actor. It suggests that I add akka.actor.dsl.Inbox. When I do that the import is greyed out because it is "not implimented", and get a compile error further down in the script when I go to implement inbox. It says "
not found: value Inbox
val inbox = Inbox.create(system)
"
What am I doing wrong? Thanks!
I would recommend you use sbt and then use the gen-idea plugin to create your intellij project.
You'll need to re-run gen-idea every time your dependencies change - intelliJ currently won't automatically discover and resolve managed dependencies for you.
here is the plugin with directions.
https://github.com/mpeltonen/sbt-idea
also, as a professional I would recommend you use the sbt console for most of your tasks.
Ctrl-tab 0 will let you hop over there without touching your mouse.
Escape brings you back to the code editor window.
You can run sbt ~test to test on change to your files etc.
Note you may need to change focus off of intellij for it to save the file in memory if you're use ~test
I managed to resolve the same issue by adding the following library from the Maven repository
com.typesafe.akka:akka-actor_2.10:2.2-M3
to File -- Project Structure -- Libraries