深入使用字段值搜索

时间:2019-07-04 13:51:28

标签: java kotlin intellij-plugin

我想编写一个检查,以跟踪对驻留在字段内的对象的方法调用。该算法对我来说是这样的:

  • 找到有趣的字段,
  • 查找给定字段的所有“读取”用法
    • 如果它是方法调用(例如field.method()),则说明已完成
    • 操作员也使用它作为方法调用
    • 如果是赋值(variable = field),请以相同的方式跟踪左手变量/字段
    • 如果它作为方法参数(method(field)),请跟踪方法参数的用法
    • 恩,也许就这些?

第一个很简单:我想支持Java和Kotlin,所以我扩展了AbstractBaseUastLocalInspectionTool,重写了checkField方法,并添加了一些检查来帮助我了解自己是否对此感兴趣字段。

然后,看起来我需要references search。好的,ReferencesSearch.search(field.sourceElement).forEach { ... }将为我的字段的每次使用调用我的lambda,但现在我陷入了困境:

  1. 给定PsiReference的分类方式是哪种?我可以得到PsiElement,它可能显示为PsiExpressionKtExpression。但也可能不会。是否有所有可能案例的详尽清单以及处理(访问)它们的方法?

  2. PsiReference.element不再是UAST。我是否应该通过UastVisitorAdapter传递任何PSI元素?

  3. 使用情况搜索似乎是检查开发中的常见模式。也许有一些更高层次的抽象可以做到这一点?

当我试图从调用中提取方法名称时,我已经写了这段代码,并且我确定许多极端情况没有得到处理:

private val PsiReference.outerMethodName: String? get() {
    val el = element
    if (el is PsiExpression) {
        ((el.parent as? PsiReferenceExpression)?.parent as? PsiMethodCallExpression)?.methodExpression?.let {
            if (this === it.qualifierExpression) {
                return it.referenceName
            }
        }
    }

    if (el is KtExpression) {
        el.context?.children?.let {
            if (it.size == 2 && (it[0] as? KtNameReferenceExpression)?.references?.firstOrNull() === this) {
                return (it[1] as? KtCallExpression)?.firstChild?.text
            }
        }
    }

    return null
}

0 个答案:

没有答案