organics2016 / pojo2json

A simple plugin for converting POJO to JSON in IntelliJ IDEA
MIT License
72 stars 37 forks source link

无法识别 Kotlin multiplatform 中非JVM平台源码集中的类 #37

Open ForteScarlet opened 4 months ago

ForteScarlet commented 4 months ago

Kotlin多平台项目中无法识别 commonMain 中定义的类型,例如 commonMain 中写的某个数据类。如果点击 Copy JSON 会在粘贴板中得到 null 。 会考虑支持Kotlin多平台吗?

organics2016 commented 4 months ago

我不太了解你说的 Kotlin多平台, 我搜索的信息认为它是一种移动端跨平台的框架, 所以我没明白你的问题, 你应该用代码展示一个例子,, 让我知道你的想法 .. 另外我也不知道你说的 commonMain 是什么? 如果它是一个标准的 Kotlin class 那么应该是支持的.. 插件会检查带有 "class"字段的 Kotlin 文件, 如果你说的 commonMain 可以被定义为一个 Kotlin class 那应该是支持的..

ForteScarlet commented 4 months ago

我创建了一个简单的 Kotlin 多平台项目,也许可以用作参考: kt-multiplatform-example.zip

Kotlin 多平台的源码集大概类似于:

root
   \- src
        \- commonMain  ---> 共享的源码集
        |      \- kotlin 
        |            \- DataCommon.kt
        \- jvmMain  -------> 专供 JVM 平台的源码集
        |      \- kotlin
        |            \--- DataJvm.kt
        \- jsMain  ---------> 专供 JS 平台的源码集

其中,commonMain 就是对所有平台都共享的源码集,可以在其他平台中访问、并被编译进对应的平台产物中(比如编译成class文件) jvmMain 是 JVM 平台的源码集,可以使用 commonMain 中的东西,但是不能使用其他平台的(比如 JS 平台 jsMain 中的类型)

遇到的问题: 在我上面提供的那个简单的项目中,有两个类,分别是定义在 commonMain 中的 DataCommon.ktjvmMain 中的 DataJvm.kt,而对 DataCommon.kt 使用 Copy JSON 只会在粘贴板中得到 nullDataJvm.kt 则是正常的。

这似乎是因为在 commonMain 中的时候, https://github.com/organics2016/pojo2json/blob/fcf403b2ef1f0ad7bced5e1bbbb8d375568cabea/src/main/java/ink/organics/pojo2json/POJO2JSONAction.java#L33-L77

POJO2JSONAction.pojo2jsonAction 里准备 uElement 的条件逻辑都没有生效,导致最终 uElement 的值为 null,因此toJson得到了值为 nulljson 并且提示了成功。

https://github.com/organics2016/pojo2json/blob/fcf403b2ef1f0ad7bced5e1bbbb8d375568cabea/src/main/java/ink/organics/pojo2json/POJO2JSONAction.java#L67

逻辑中定位到的 elementAt (例如 PsiElement elementAt = psiFile.findElementAt(offset);)是有值的,但是它们似乎无法被解析为UClass 之类的类型 🤔。

我不太了解插件开发,因此想要尝试自行修复但是没有成功,也无法定位到更根本的原因,还望见谅😢

organics2016 commented 4 months ago

收到你的回复,,我已经成功复现, 我需要一些时间解决这个BUG

organics2016 commented 4 months ago

感谢你的回复, 可以确定这是一个BUG, 但遗憾的是短时间无法修复. https://github.com/organics2016/pojo2json/blob/fcf403b2ef1f0ad7bced5e1bbbb8d375568cabea/src/main/java/ink/organics/pojo2json/POJO2JSONAction.java#L63 问题在这里, 这可能是 jetbrains plugins SDK 的问题, DataCommon.ktDataJvm.kt 格式上没有任何区别, 但却返回两种不同的结果. 准确的说 commonMain 文件夹下的 kt 文件都无法被正确的解析为 UElement 我对此也很懵逼. JB SDK 的抽象语法引擎实现就是一坨....

https://github.com/organics2016/pojo2json/blob/fcf403b2ef1f0ad7bced5e1bbbb8d375568cabea/src/main/java/ink/organics/pojo2json/POJO2JSONAction.java#L55-L64 这段代码逻辑是: 当用户光标在文件没有元素的区域进行 Copy JSON 时, 会自动查找这个文件中 class 关键字 并将这个关键字所在的元素解析为 抽象语法树中的 UElement . 但是对于 commonMain 文件夹下的所有 kt 文件解析结果却是 null.

这个问题我的去 jetbrains plugins SDK 提Issue.. 短时间内应该无法解决.

ForteScarlet commented 4 months ago

👌🏻已了解

不知道会不会有别的不用 UElement 的实现方法呢?🤔

这方面不太了解,只是随口说说 , 总而言之辛苦排查了,期待修复的那一天~

organics2016 commented 4 months ago

目前最有可能的解释是 IDEA 为 commonMainjvmMain 两个文件夹 加载了两种不同的包环境 , 因为环境中的lib不一样 , 导致语法树引擎认为它们不一样... 之前也有类似的情况. 我已经尝试将 UElement 当作原始的 PsiElement 进行处理,结果所有 kt 文件都会失效....情况比现在更差..我暂时也没什么好办法了..

ForteScarlet commented 4 months ago

好吧,看来需要等待JB对Issue的答复了

organics2016 commented 4 months ago

https://intellij-support.jetbrains.com/hc/en-us/community/posts/19466336231186--BUG-org-jetbrains-uast-UastUtils-findContaining-Unable-to-recognize-Kotlin-class-in-Kotlin-multiplatform