Kotlin多平台项目启用kspJs报「集合包含多个元素」错误如何解决?
问题解决方案
根因分析
你遇到的报错核心原因有两个:
- 你的KSP处理器当前仅构建了JVM变体,当你给
kspJs添加依赖时,Gradle默认会尝试查找JS平台的处理器构件,找不到的情况下会触发依赖解析异常,即使解析通过,也会出现第二个问题 - 你将
@Observable注解放在了commonMain源集下,同时启用JVM和JS的KSP配置后,KSP会分别为两个平台各生成一份BlahO.kt,分别输出到jvmMain和jsMain的生成目录,JS编译阶段扫描到两份完全同名同包的类,无法确定入口,就抛出「Collection has more than one element.」的错误。
解决步骤
你可以根据自己的需求选其中一种方案:
方案1:仅在JVM侧运行KSP,生成公共代码给所有平台使用
如果你的处理器生成的代码是跨平台兼容的,不需要为JS做特殊处理,可以用这个方案,不需要启用kspJs:
- 去掉
kspJs的依赖配置,保留kspJvm的配置 - 在消费者侧的
build.gradle.kts中添加配置,将JVM侧KSP生成的代码纳入commonMain的源集,让JS平台也能访问到:
kotlin.sourceSets.commonMain { kotlin.srcDir("build/generated/ksp/jvmMain/kotlin") }
- 重新构建即可,此时只会生成一份公共代码,两个平台都能正常访问。
方案2:同时启用多平台KSP,避免生成重复类
如果你需要为不同平台生成不同的实现,可以用这个方案:
- 先给
kspJs的依赖显式指定使用JVM变体(KSP处理器本身是运行在Gradle JVM上的,不需要JS版本):
dependencies { add("kspJvm", "io.jvaas:jvaas-observe") add("kspJs", "io.jvaas:jvaas-observe") { attributes { attribute(org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.attribute, org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm) } } }
- 调整处理器的代码生成逻辑,指定生成的代码归属到对应平台的源集,不要让生成的类跨平台可见,或者将
@Observable注解从commonMain移到各个平台的源集下分别添加,避免KSP重复处理同一个类生成两份代码。 - 建议升级你当前使用的KSP版本,1.6.0-1.0.1属于非常早期的KSP版本,对多平台的支持存在不少已知bug,可以升级到Kotlin 1.6.x对应的最新KSP版本
1.6.21-1.0.6,避免触发已经修复的问题。
内容的提问来源于stack exchange,提问作者Jan Vladimir Mostert
相关产品推荐
相关产品推荐

