java.util.ServiceConfigurationError when trying to compile a .kts script from a plugin

Answered

I am building a plugin for IDEA, and I am trying to compile a custom kts script from the plugin.

I am able to run the script from the command line and have managed to get the script definition picked up by IDEA, so autocompletion etc inside the script do work.

Following examples like this one, this is what I have set up:

(the markdown dependency is there for other purposes)

gradle file:

dependencies {
api(project(":script"))
implementation("org.jetbrains.kotlin:kotlin-scripting-jvm:$kotlinVersion")
compileOnly("org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlinVersion")
testRuntimeOnly("org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlinVersion")
}

intellij {
pluginName.set("Confis")
version.set("IC-213.5744.223")
type.set("IC")

plugins.set(
listOf(
"Kotlin",
"java",
"org.intellij.plugins.markdown"
)
)
}

plugin.xml dependencies:

    <depends>com.intellij.modules.platform</depends>
    <depends>org.jetbrains.kotlin</depends>
    <depends>org.intellij.plugins.markdown</depends>

Going from VirtualFile to SourceCode:

import kotlin.script.experimental.api.SourceCode

data class MySourceCode(
    override val locationId: String?,
    override val name: String?,
    override val text: String,
) : SourceCode

val scriptFile: VirtualFile // the file for my custom .confis.kts script

val source = MySourceCode(scriptFile.url, scriptFile.name, scriptDocument.text)

 

Compiling:

val host = BasicJvmScriptingHost()
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MyScriptDefinition>()


val res: ResultWithDiagnostics<EvaluationResult> =
defaultHost.eval(source, compilationConfiguration, null)

// res is ResultWithDiagnostics.Failure

Where `res` is a ResultWithDiagnostics.Failure. The only `ERROR` level diagnostic is:

ERROR org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension: org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages not a subtype (example.confis.kts): java.util.ServiceConfigurationError: org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension: org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages not a subtype

 

I am at a loss of the meaning of the error. I tried using the embeddable and not embeddable examples from the scripting repo I posted above. Again, I believe this must have something to do with how the classpath of the plugin looks like, because I am able to use BasicJvmScriptingHost().eval() just fine in a standalone project

 

Thanks in advance!

3 comments
Comment actions Permalink

Seems like it might be related to  this commit - FirDefaultErrorMessages used to inherit from DefaultMessages.Extension. It still does inside `kotlin-compiler-for-ide-1.5.10-release-949.jar`, but I am using Kotlin plugin version 1.6.20 

0
Comment actions Permalink

I updated IDEA to the latest version and now the EvaluationResult displays a different error:

- Cannot access script base class 'eu.dcotta.confis.dsl.MyScriptBaseClass'. Check your module classpath for missing or conflicting dependencies

where eu.dcotta.confis.dsl.MyScriptBaseClass is the class my ScriptDefinition inherits from

0
Comment actions Permalink

I fixed using dependencies inside the custom script by using

// ConfisScriptDefinition is inside a different Jar
// ConfisHost and this code are inside the plugin jar

private val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<ConfisScriptDefinition> {
        jvm {
          // using the plugin's classloader here is what made using my script dependencies possible
            dependenciesFromClassloader(classLoader = ConfisHost::class.java.classLoader, wholeClasspath = true)
      }
  }

Because it turns out that dependenciesFromCurrentContext uses Thread.current().contextClassLoader and that one does not correspond to the plugin classloader.

I still have not managed to use the compiled script instance inside the plugin. I now have a different problem, still caused by the plugin's classloader. More details in this new post.

1

Please sign in to leave a comment.