为什么调用 KotlinCoreEnvironment.createForProduction 会导致 IllegalStateException?
Why does calling KotlinCoreEnvironment.createForProduction cause IlegalStateException?
我对将 Kotlin 程序解析为其 PSI 元素感兴趣。在阅读了一些资料之后,我首先通过创建环境来设置项目,并将 Kotlin 源代码作为字符串转换为 KtFile
。但是,调用 KotlinCoreEnvironment.createForProduction(parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles)
似乎会触发此 java.lang.IllegalStateException
错误。
谷歌搜索后,我尝试将 JDK 从 11 更改为 8,但没有解决问题。关于如何解决这个问题有什么建议吗?
错误信息如下:
Exception in thread "main" java.lang.IllegalStateException: LOGGING: Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.incubator.foreign, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.nio.mapmode, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt] (no MessageCollector configured)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.report(ClasspathRootsResolver.kt:332)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.report$default(ClasspathRootsResolver.kt:330)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.addModularRoots(ClasspathRootsResolver.kt:273)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.computeRoots(ClasspathRootsResolver.kt:128)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.convertClasspathRoots(ClasspathRootsResolver.kt:84)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:267)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:111)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:475)
at docGenerator.DocKt.createKtFile(Doc.kt:70)
at docGenerator.DocKt.generateDocs(Doc.kt:27)
at MainKt.main(Main.kt:10)
at MainKt.main(Main.kt)
Process finished with exit code 1
而我的build.gradle
目前是这样的:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.6.0'
id 'org.jetbrains.intellij' version '1.2.1'
}
group 'me.ylee'
version '1.0-SNAPSHOT'
repositories {
google()
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.6.0"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.21"
implementation 'net.java.dev.jna:jna:5.11.0'
implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
}
intellij {
plugins = ['Kotlin']
}
compileKotlin {
kotlinOptions.jvmTarget = '1.8'
}
compileTestKotlin {
kotlinOptions.jvmTarget = '1.8'
}
明确一点,当我在创建 KtFile
时调用 KotlinCoreEnvironment.createForProduction
,我相信我正在导入所有正确的...如果我在任何地方弄错了请纠正我并查看下面的代码片段(标有 >>
的行)。
import org.jetbrains.kotlin.com.intellij.openapi.fileTypes.FileType
import org.jetbrains.kotlin.com.intellij.openapi.Disposable
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.com.intellij.psi.PsiManager
import org.jetbrains.kotlin.com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.psi.KtFile
...
fun createKtFile(codeString: String, fileName: String): KtFile {
val disposable: Disposable = Disposer.newDisposable()
val config = CompilerConfiguration()
val configFiles: EnvironmentConfigFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
try {
val proj =
>> KotlinCoreEnvironment.createForProduction(disposable, config, configFiles).project
val fileType: FileType = KotlinFileType.INSTANCE as FileType
val file = LightVirtualFile(fileName, fileType, codeString)
return PsiManager.getInstance(proj).findFile(file) as KtFile
} finally {
disposable.dispose()
}
}
顺便说一句,我试过的建议,比如使用最新版本的 org.jetbrains.itellij
并没有真正奏效,因为使用最新版本,我无法构建项目。
正如@Alexey Belkov 在评论中所建议的那样,我必须将消息收集器实例添加到编译器配置中。
下面的代码现在可以工作了。
fun createKtFile(codeString: String, fileName: String): KtFile {
val disposable: Disposable = Disposer.newDisposable()
val config = CompilerConfiguration()
config.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false))
val configFiles: EnvironmentConfigFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
try {
val env =
KotlinCoreEnvironment.createForProduction(disposable, config, configFiles)
val fileType: FileType = KotlinFileType.INSTANCE as FileType
val file = LightVirtualFile(fileName, fileType, codeString.trimIndent())
val res: KtFile = PsiManager.getInstance(env.project).findFile(file) as KtFile
return res
} finally {
disposable.dispose()
}
}
我对将 Kotlin 程序解析为其 PSI 元素感兴趣。在阅读了一些资料之后,我首先通过创建环境来设置项目,并将 Kotlin 源代码作为字符串转换为 KtFile
。但是,调用 KotlinCoreEnvironment.createForProduction(parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles)
似乎会触发此 java.lang.IllegalStateException
错误。
谷歌搜索后,我尝试将 JDK 从 11 更改为 8,但没有解决问题。关于如何解决这个问题有什么建议吗?
错误信息如下:
Exception in thread "main" java.lang.IllegalStateException: LOGGING: Loading modules: [java.se, jdk.accessibility, jdk.attach, jdk.compiler, jdk.dynalink, jdk.httpserver, jdk.incubator.foreign, jdk.jartool, jdk.javadoc, jdk.jconsole, jdk.jdi, jdk.jfr, jdk.jshell, jdk.jsobject, jdk.management, jdk.management.jfr, jdk.net, jdk.nio.mapmode, jdk.sctp, jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.unsupported.desktop, jdk.xml.dom, java.base, java.compiler, java.datatransfer, java.desktop, java.xml, java.instrument, java.logging, java.management, java.management.rmi, java.rmi, java.naming, java.net.http, java.prefs, java.scripting, java.security.jgss, java.security.sasl, java.sql, java.transaction.xa, java.sql.rowset, java.xml.crypto, jdk.internal.jvmstat, jdk.management.agent, jdk.jdwp.agent, jdk.internal.ed, jdk.internal.le, jdk.internal.opt] (no MessageCollector configured)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.report(ClasspathRootsResolver.kt:332)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.report$default(ClasspathRootsResolver.kt:330)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.addModularRoots(ClasspathRootsResolver.kt:273)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.computeRoots(ClasspathRootsResolver.kt:128)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.convertClasspathRoots(ClasspathRootsResolver.kt:84)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:267)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:111)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:475)
at docGenerator.DocKt.createKtFile(Doc.kt:70)
at docGenerator.DocKt.generateDocs(Doc.kt:27)
at MainKt.main(Main.kt:10)
at MainKt.main(Main.kt)
Process finished with exit code 1
而我的build.gradle
目前是这样的:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.6.0'
id 'org.jetbrains.intellij' version '1.2.1'
}
group 'me.ylee'
version '1.0-SNAPSHOT'
repositories {
google()
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.6.0"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.21"
implementation 'net.java.dev.jna:jna:5.11.0'
implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
}
intellij {
plugins = ['Kotlin']
}
compileKotlin {
kotlinOptions.jvmTarget = '1.8'
}
compileTestKotlin {
kotlinOptions.jvmTarget = '1.8'
}
明确一点,当我在创建 KtFile
时调用 KotlinCoreEnvironment.createForProduction
,我相信我正在导入所有正确的...如果我在任何地方弄错了请纠正我并查看下面的代码片段(标有 >>
的行)。
import org.jetbrains.kotlin.com.intellij.openapi.fileTypes.FileType
import org.jetbrains.kotlin.com.intellij.openapi.Disposable
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.com.intellij.psi.PsiManager
import org.jetbrains.kotlin.com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.psi.KtFile
...
fun createKtFile(codeString: String, fileName: String): KtFile {
val disposable: Disposable = Disposer.newDisposable()
val config = CompilerConfiguration()
val configFiles: EnvironmentConfigFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
try {
val proj =
>> KotlinCoreEnvironment.createForProduction(disposable, config, configFiles).project
val fileType: FileType = KotlinFileType.INSTANCE as FileType
val file = LightVirtualFile(fileName, fileType, codeString)
return PsiManager.getInstance(proj).findFile(file) as KtFile
} finally {
disposable.dispose()
}
}
顺便说一句,我试过的建议,比如使用最新版本的 org.jetbrains.itellij
并没有真正奏效,因为使用最新版本,我无法构建项目。
正如@Alexey Belkov 在评论中所建议的那样,我必须将消息收集器实例添加到编译器配置中。
下面的代码现在可以工作了。
fun createKtFile(codeString: String, fileName: String): KtFile {
val disposable: Disposable = Disposer.newDisposable()
val config = CompilerConfiguration()
config.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false))
val configFiles: EnvironmentConfigFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
try {
val env =
KotlinCoreEnvironment.createForProduction(disposable, config, configFiles)
val fileType: FileType = KotlinFileType.INSTANCE as FileType
val file = LightVirtualFile(fileName, fileType, codeString.trimIndent())
val res: KtFile = PsiManager.getInstance(env.project).findFile(file) as KtFile
return res
} finally {
disposable.dispose()
}
}