Customised Kotlin scripts support in IntelliJ

Answered

Hi IntelliJ,

Currently the IDE support is only for .main.kts Kotlin scripts? Is there any way to enable the support for customised Kotlin scripts such as .simple.kts or whatever? I created a template and an engine for my scrips but unfortunately those scripts has plenty of uresolve reference errors.

1
3 comments
Hi there, 

You can take a look at this guide: https://kotlinlang.org/docs/custom-script-deps-tutorial.html
It explains how to set up support for custom Kotlin script types like `.simple.kts`.

If you follow that and still keep seeing unresolved reference errors, it would be great if you could report it to us here: https://youtrack.jetbrains.com/newissue?project=KT so the team can take a closer look.

Thanks!
1

You're hitting a common challenge when working with custom Kotlin scripts in IntelliJ IDEA beyond the standard .main.kts or build.gradle.kts files. The "unresolved reference errors" indicate that IntelliJ's IDE is not fully aware of the classpath and script definition for your .simple.kts files.

Here's a breakdown of why this happens and how you can approach enabling proper support:

Why you're seeing unresolved reference errors:

  • IntelliJ's default script recognition: IntelliJ IDEA has built-in support for .kts files, particularly for Gradle Kotlin DSL (build.gradle.kts) and standalone main.kts scripts. However, for custom extensions like .simple.kts, it doesn't automatically know how to compile them or what dependencies they might have.
  • Missing script definition: For Kotlin scripts to function correctly and for the IDE to provide proper coding assistance (completion, error highlighting, navigation), they need a "script definition." A script definition tells the Kotlin compiler and the IDE about:
    • The base class for your script.
    • Any implicit imports.
    • Default dependencies (e.g., if your scripts always use a certain library).
    • The file extension(s) it should recognize.
  • Classpath issues: Even if you have a script definition, IntelliJ needs to know where to find the classes and functions that your scripts are referencing. If your custom scripts rely on code within your project or external libraries, IntelliJ might not be adding those to the script's perceived classpath.

How to enable support for customized Kotlin scripts in IntelliJ IDEA:

The core idea is to teach IntelliJ about your custom script type by providing a proper Kotlin Script Definition. This often involves creating a separate module in your project.

Here's a general approach, drawing from the Kotlin documentation and community discussions:

  1. Create a Script Definition Module:
    • In your IntelliJ project, create a new Gradle (or Maven) module. This module will house your script definition.
    • Add the necessary Kotlin scripting dependencies to this module's build.gradle.kts (or pom.xml): 

      Kotlin

       

      dependencies {
          implementation(kotlin("scripting-common"))
          implementation(kotlin("scripting-jvm"))
          implementation(kotlin("scripting-jvm-host"))
          // Add any other dependencies your scripts might implicitly need
      }
      
  2. Define your Script Template:
    • In your script definition module, create a Kotlin class that will serve as your script template. This class needs to be annotated with @KotlinScript.
    • Example: 

      Kotlin

       

      // In your script definition module (e.g., src/main/kotlin/com/example/SimpleScriptTemplate.kt)
      package com.example
      
      import kotlin.script.templates.standard.ScriptTemplateWith\]
      import kotlin.script.experimental.annotations.KotlinScript
      import kotlin.script.experimental.api.ScriptCompilationConfiguration
      import kotlin.script.experimental.api.SourceCode
      import kotlin.script.experimental.jvm.JvmScriptCompilationConfiguration
      import kotlin.script.experimental.jvm.dependenciesFromClassloader
      import kotlin.script.experimental.jvm.jvm
      import kotlin.script.experimental.host.StringScriptSource
      
      @KotlinScript(
          fileExtension = "simple.kts", // Your custom file extension
          compilationConfiguration = SimpleScriptConfiguration::class
      )
      abstract class SimpleScriptTemplate
      
      object SimpleScriptConfiguration : ScriptCompilationConfiguration({
          // Configure your script here.
          // For example, if your scripts need access to your project's classes,
          // you'll need to specify dependencies.
          // This is a common source of "unresolved reference" errors.
          jvm {
              dependenciesFromClassloader(
                  "kotlin-stdlib",
                  "kotlin-reflect",
                  // Add other libraries or project modules your scripts depend on
                  // For project modules, this can be tricky. You might need to
                  // build your project and then depend on the generated JARs,
                  // or find a way to include the project's output directly.
                  // A common workaround is to put custom scripts *inside* a source
                  // root (e.g., src/main/kotlin) for easier classpath resolution.
              )
          }
          // Add any default imports
          defaultImports(
              "java.io.*",
              "java.util.*",
              "kotlin.collections.*",
              // Your custom imports
          )
          // You can also add script arguments if your scripts take them
          // scriptEngine.arguments("myArgument1", "myArgument2")
      })
      
  3. Register the Script Definition in META-INF:
    • In your script definition module, create the following directory structure: src/main/resources/META-INF/kotlin/script/templates/
    • Inside this templates directory, create an empty file with the fully qualified name of your script template class. For the example above, the file name would be com.example.SimpleScriptTemplate. Ensure there's no .class or .kt extension in the file name itself.
  4. Configure IntelliJ IDEA:
    • Build the script definition module: Make sure your script definition module is built. This will generate the necessary JAR containing your script definition.
    • Add module dependency (if applicable): If your custom scripts reside in a separate module from the script definition, ensure that the module containing your .simple.kts files has a dependency on your script definition module.
    • Refresh Gradle/Maven project: After making these changes, refresh your Gradle or Maven project in IntelliJ IDEA.
    • Increase script priority (important for proper IDE recognition):
      • Go to File | Settings/Preferences | Languages & Frameworks | Kotlin | Kotlin Scripting.
      • You should see your custom script definition listed there.
      • Increase its priority above the generic .kts scripts. This ensures IntelliJ uses your specific definition for your .simple.kts files. This is a common pitfall.
    • Invalidate Caches and Restart: Sometimes, IntelliJ needs a full refresh to pick up new script definitions. Go to File | Invalidate Caches / Restart... and select "Invalidate and Restart."
  5. Running and Debugging Custom Scripts:
    • Once your script definition is recognized, you should see proper syntax highlighting and code completion.
    • To run your .simple.kts files, you can usually create a "Kotlin Script" run/debug configuration in IntelliJ IDEA. In this configuration, specify the path to your .simple.kts file. IntelliJ should then use your registered script definition to execute it.

Common causes of unresolved reference errors and troubleshooting:

  • Missing META-INF file: Double-check the path and name of the empty file in META-INF/kotlin/script/templates/. It must be the exact fully qualified name of your @KotlinScript annotated class.
  • Incorrect dependencies in ScriptCompilationConfiguration: The dependenciesFromClassloader in your ScriptCompilationConfiguration is crucial. If your scripts use classes from your project or external libraries, those need to be explicitly available to the script's classloader. This is often the hardest part.
    • Project dependencies: If your scripts depend on code within your main project, one common workaround is to place the custom .kts files inside a source root (e.g., src/main/kotlin). This often helps IntelliJ resolve project-internal references more easily. However, be aware that IntelliJ might warn you that "This script is not supposed to be inside source root" in newer Kotlin versions, as they might be ignored during module compilation in Kotlin 1.9+.
    • External JARs: If your scripts depend on external JARs, you might need to ensure those JARs are on the classpath when the script is being compiled and run. The dependenciesFromClassloader can help here, but you might need to be PrepaidCardStatus Login explicit about the names.
  • IntelliJ Caches: As mentioned, sometimes a simple "Invalidate Caches and Restart" is all that's needed for IntelliJ to pick up the new configuration.
  • Version Mismatches: Ensure your Kotlin plugin version in IntelliJ IDEA matches the Kotlin version used in your project's build.gradle.kts. Mismatches can lead to various IDE issues, including unresolved references.
  • Gradle/Maven Sync Issues: Always re-sync your Gradle/Maven project after making changes to build files or script definitions.

It's a bit of a setup process, but once you have your custom script definition properly configured, IntelliJ IDEA's support for your .simple.kts files should dramatically improve, giving you the coding assistance you need.

3

Thanks both, all was very useful.

0

Please sign in to leave a comment.