题目是关于静态编译时分析的。假设有一个文件级
const val
:
const val SOME_CONST_VAL = "SOME_CONST_VAL"
如何获得这个
SOME_CONST_VAL
的使用次数?
澄清一下:
已检查:
这里最好的方向是什么?
经过一段时间的反复试验(主要是错误🙂)我可以部分回答我的问题。
我尽量避开有编译器插件的路径,因为上面的资料不多。官方 Kotlin 文档仅提供此类插件的示例 - 没有概述或至少没有基本的概念说明,各种第 3 方文章大多建议通过查看现有的编译器插件来指导自己。同时相应的API可能会发生变化,所以我决定这样推迟。
我的注意力集中在尝试为此扩展检测。在我看来,对于问题中描述的任务来说,这绝对是一种错误的工具。理由是:
用于分析代码的访问者范围仅限于单独的源
KtFile
s。不确定是否可以参考一些 detekt 文档页面来说明这一点,但可以从其 API 中推断出来(也可以在相应的 GitHub 讨论中找到说明它的直接答案)。
#1 的结果是没有办法编写这样的规则:没有方法让规则实现在所有文件都被访问后做一些处理。如果我们对访问的每个文件都进行必要的检查,我们将没有足够的信息来说明整个代码库中是否使用了某个变量。当然可以尝试做肮脏的变通办法——例如通过使用静态集合来积累访问过的引用并最终触发它们的整个验证,但它似乎并不稳定。
编写自定义处理器似乎是可能的,因为它会在访问所有文件时触发回调。但在这种情况下,我们在 detekt 允许处理者报告的方式上遇到了限制——它只提供定量报告的方式。当然也可以把我们要报告的所有内容都包含到
ProjectMetric::type
字符串中,但我猜总有一天会被限制的。
无法对所有变量和其他各种引用使用类似于依赖树的东西进行操作。代码分析更像是基于令牌的字符串阅读。我尝试根据
FullQualifiedNameGuesser
的用法尝试一些启发式方法,但它并没有提供稳定的结果来尝试查找某些用法的声明。
即使以上所有点都可以通过一些变通方法解决,它也会产生巨大的性能矫枉过正,因为我们基本上收集了整个代码库中的所有声明和所有引用并最终匹配它们。
总结一下:我认为尝试通过其可用的 API 来扩展 detekt 似乎是解决问题中描述的问题的死胡同。去检查别的东西。
更新 (20.4.23) - 尝试过 Qodana,
UnusedSymbol
检查做了类似的事情(从另一边稍微),但它不是很可扩展(通过代码方式)并且需要 Docker 运行。也可以使用 Structural Search 并导出其模板以与 Qodana 一起运行,但它似乎又不是我需要的东西。