Android Studio插件开发:KtFile类型转换ClassCastException问题求助
错误信息
java.lang.ClassCastException: class org.jetbrains.kotlin.psi.KtFile cannot be cast to class org.jetbrains.kotlin.psi.KtFile (org.jetbrains.kotlin.psi.KtFile is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @6bf6bf87; org.jetbrains.kotlin.psi.KtFile is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @62ccc687) at com.ordinarythinker.jcat.ProcessKtFileAction.actionPerformed(ProcessKtFileAction.kt:24)
异常抛出在val ktFile = psiFile as KtFile行,对应代码如下:
import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction class ProcessKtFileAction : AnAction() { override fun actionPerformed(e: AnActionEvent) { val project: Project = e.project ?: return val file: VirtualFile? = e.getData(CommonDataKeys.VIRTUAL_FILE) if (file != null && file.isValid) { val psiFile: PsiFile? = e.getData(CommonDataKeys.PSI_FILE) try { val ktFile = psiFile as KtFile // exception is thrown here } catch (e: Exception) { e.printStackTrace() } } } // some other code }
问题根源
类加载器不同导致类型转换失败,尽管调试显示PsiFile确实是KtFile实例,但两个KtFile类分别由不同的插件类加载器加载,JVM认为它们是不同类型。
已配置内容
build.gradle.kts
plugins { id("org.jetbrains.intellij") version "1.16.0" id("org.jetbrains.kotlin.jvm") version "1.9.21" } group = "com.ordinarythinker" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { implementation(kotlin("compiler-embeddable", "1.9.21")) implementation(kotlin("reflect")) } apply(plugin = "org.jetbrains.intellij") apply(plugin = "kotlin") intellij { version.set("2022.3.1") type.set("IC") plugins.set(listOf("android", "Kotlin")) } tasks { withType<JavaCompile> { sourceCompatibility = "17" targetCompatibility = "17" } withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { kotlinOptions.jvmTarget = "17" } runIde { ideDir.set(file("C:\\Program Files\\Android\\Android Studio2")) } patchPluginXml { sinceBuild.set("223") untilBuild.set("241.*") } signPlugin { certificateChain.set(System.getenv("CERTIFICATE_CHAIN")) privateKey.set(System.getenv("PRIVATE_KEY")) password.set(System.getenv("PRIVATE_KEY_PASSWORD")) } publishPlugin { token.set(System.getenv("PUBLISH_TOKEN")) } }
gradle.properties
kotlin.stdlib.default.dependency = false
plugin.xml
<idea-plugin> <id>com.ordinarythinker.jCat</id> <name>jCat</name> <vendor email="" url="https://github.com/ordinarythinker">Andrii D.</vendor> <description><![CDATA[ JCat is a plugin for automated tests generation for Composable functions<br> <em>Currently is underway the development</em> ]]></description> <depends>com.intellij.modules.platform</depends> <extensions defaultExtensionNs="com.intellij"> </extensions> <actions> <action id="ProcessKtFileAction" class="com.ordinarythinker.jcat.ProcessKtFileAction" text="Generate Test" description="Generate test"> <add-to-group group-id="EditorPopupMenu" anchor="last"/> </action> </actions> <depends>org.jetbrains.kotlin</depends> </idea-plugin>
已尝试无效方案
已将org.jetbrains.kotlin添加到intellij块的plugins列表,问题仍未解决。
解决方案
移除冲突的Kotlin依赖
从dependencies块中删除implementation(kotlin("compiler-embeddable", "1.9.21")),IntelliJ插件SDK已包含Kotlin相关库,手动添加会引发类加载器冲突。调整依赖范围为
compileOnly
将Kotlin反射依赖改为compileOnly,避免打包进插件:dependencies { compileOnly(kotlin("reflect")) }确保插件依赖声明顺序正确
在plugin.xml中,将org.jetbrains.kotlin依赖放在com.intellij.modules.platform之后,确认依赖的Kotlin插件ID为org.jetbrains.kotlin(Android Studio中无需修改)。清理并重新构建项目
执行以下Gradle任务,清除旧构建产物:cleanbuildPluginrunIde
使用安全类型检查替代强转
在代码中先进行类型判断,避免直接强制转换:if (psiFile is KtFile) { // 处理KtFile逻辑 val ktFile = psiFile } else { // 非Kotlin文件处理逻辑 }匹配Android Studio版本
确认intellij块中的version(2022.3.1)与runIde中指定的本地Android Studio版本一致,版本不匹配也会导致类加载器问题。
内容的提问来源于stack exchange,提问作者Andrii Nexter

