pinterest / ktlint

An anti-bikeshedding Kotlin linter with built-in formatter
https://pinterest.github.io/ktlint/
MIT License
6.19k stars 505 forks source link

ClassCastException when embedding ktlint #2507

Closed canatella closed 8 months ago

canatella commented 8 months ago

Expected Behavior

When embedding ktlint 1.1.1 in another project, I get this exception when running the project:

$ ./server/build/install/server/bin/kotlin-language-server 
Exception in thread "main" java.lang.ExceptionInInitializerError
        at com.pinterest.ktlint.ruleset.standard.rules.AnnotationRule.<clinit>(AnnotationRule.kt:470)
        at com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider$getRuleProviders$1.invoke(StandardRuleSetProvider.kt:103)
        at com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider$getRuleProviders$1.invoke(StandardRuleSetProvider.kt:103)
        at com.pinterest.ktlint.rule.engine.core.api.RuleProvider$Companion.invoke(RuleProvider.kt:41)
        at com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider.getRuleProviders(StandardRuleSetProvider.kt:103)
        at org.javacs.kt.formatting.Formatter$KtLint.<init>(Formatter.kt:32)
        at org.javacs.kt.KotlinTextDocumentService.<init>(KotlinTextDocumentService.kt:71)
        at org.javacs.kt.KotlinLanguageServer.<init>(KotlinLanguageServer.kt:36)
        at org.javacs.kt.KotlinLanguageServer.<init>(KotlinLanguageServer.kt:25)
        at org.javacs.kt.MainKt.main(Main.kt:42)
Caused by: java.lang.ClassCastException: class org.jetbrains.kotlin.psi.stubs.elements.KtFileElementType cannot be cast to class org.jetbrains.kotlin.com.intellij.psi.tree.IElementType (org.jetbrains.kotlin.psi.stubs.elements.KtFileElementType and org.jetbrains.kotlin.com.intellij.psi.tree.IElementType are in unnamed module of loader 'app')
        at com.pinterest.ktlint.rule.engine.core.api.ElementType.<clinit>(ElementType.kt:13)

I tried to ensure the kotlin compiler version is 1.9.22 as in ktlint 1.1.1, here is the class path:

ls -1 server/build/install/server/lib/
annotations-13.0.jar
checker-qual-2.11.1.jar
ec4j-core-0.3.0.jar
error_prone_annotations-2.3.4.jar
exposed-core-0.37.3.jar
exposed-dao-0.37.3.jar
exposed-jdbc-0.37.3.jar
failureaccess-1.0.1.jar
fernflower-1.0.jar
google-java-format-1.8.jar
gson-2.9.1.jar
guava-29.0-jre.jar
h2-1.4.200.jar
j2objc-annotations-1.3.jar
jcommander-1.78.jar
jline-3.3.1.jar
jna-4.2.2.jar
jsr305-3.0.2.jar
kotlin-compiler-1.9.22.jar
kotlin-compiler-embeddable-1.9.22.jar
kotlin-daemon-embeddable-1.9.22.jar
kotlin-logging-jvm-5.1.4.jar
kotlin-reflect-1.9.22.jar
kotlin-sam-with-receiver-compiler-plugin-1.9.22.jar
kotlin-scripting-common-1.9.22.jar
kotlin-scripting-compiler-1.9.22.jar
kotlin-scripting-compiler-impl-1.9.22.jar
kotlin-scripting-jvm-1.9.22.jar
kotlin-scripting-jvm-host-unshaded-1.9.22.jar
kotlin-script-runtime-1.9.22.jar
kotlin-stdlib-1.9.22.jar
kotlin-stdlib-jdk7-1.9.22.jar
kotlin-stdlib-jdk8-1.9.22.jar
kotlinx-coroutines-core-jvm-1.6.0.jar
ktfmt-b5d31d1.jar
ktlint-cli-ruleset-core-1.1.1.jar
ktlint-logger-1.1.1.jar
ktlint-rule-engine-1.1.1.jar
ktlint-rule-engine-core-1.1.1.jar
ktlint-ruleset-standard-1.1.1.jar
listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
org.eclipse.lsp4j-0.15.0.jar
org.eclipse.lsp4j.generator-0.15.0.jar
org.eclipse.lsp4j.jsonrpc-0.15.0.jar
org.eclipse.xtend.lib-2.24.0.jar
org.eclipse.xtend.lib.macro-2.24.0.jar
org.eclipse.xtext.xbase.lib-2.24.0.jar
poko-annotations-jvm-0.15.2.jar
server-1.3.10.jar
shared-1.3.10.jar
slf4j-api-1.7.25.jar
sqlite-jdbc-3.41.2.1.jar
trove4j-1.0.20200330.jar
paul-dingemans commented 8 months ago

What do you mean with "embedding in another project"? Do you integrate in another than one of the ways described on https://pinterest.github.io/ktlint/latest/install/integrations/? Why do you want to do it differently?

In ktlint-intellij-plugin there was also a need to really embed ktlint into the plugin. In that project the ktlint library was wrapped into a library; with the shadow plugin the org.jetbrains packages have been moved to a different location to avoid class loading conflict.

canatella commented 8 months ago

I'm trying to add support to https://github.com/fwcd/kotlin-language-server to be able to have it format files using ktlint, see https://github.com/fwcd/kotlin-language-server/issues/303. At the moment I'm just doing

        val ktLintRuleEngine = KtLintRuleEngine(
            ruleProviders = StandardRuleSetProvider().getRuleProviders()
        )
paul-dingemans commented 8 months ago

The problem is most likely caused by conflicting dependencies in your project (https://github.com/fwcd/kotlin-language-server/blob/main/platform/build.gradle.kts#L16-L26) and similar but not identical dependencies of Ktlint. This is the same problem that the ktlint-intellij-plugin had. So in ktlint plugin a lib is created in which the Ktlint dependencies are relocated to a different package (https://github.com/nbadal/ktlint-intellij-plugin/blob/main/lib/build.gradle.kts#L44). Then the lib is included in the plugin app instead of including the Ktlint dependencies (https://github.com/nbadal/ktlint-intellij-plugin/blob/main/settings.gradle.kts#L7).