You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

现有Detector可检测普通方法调用,如何在Android Lint中检测特定方法引用?

Android Lint如何检测特定类型的方法引用调用?

我目前有一个能检测onError方法直接调用的Lint Detector,但它没法识别方法引用形式的调用。以下是我现有的Detector代码:

class RxOnErrorDetector : Detector(), Detector.UastScanner {
    override fun getApplicableMethodNames() = listOf("onError")
    override fun visitMethod(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        if (context.evaluator.isMemberInClass(method, "io.reactivex.Emitter")) {
            context.report(ISSUE_ON_ERROR_CALL, node, context.getNameLocation(node), "onError method was called.")
        }
    }
}

而我想要检测的方法引用调用示例如下:

public class ObservableMethodReferenceProducer {
    private Listener listener = new Listener();
    public Observable<Integer> produceObservable() {
        return Observable.create(e -> {
            listener.doOnError(e::onError);
        });
    }
    class Listener {
        void doOnError(ErrorListener errorListener) {}
    }
    interface ErrorListener {
        void onError(Exception e);
    }
}

请问在Android Lint中检测这类特定类型的方法引用调用的最佳方式是什么?


解决方案

要解决这个问题,核心是理解:你的原始Detector只处理了直接方法调用(对应UAST中的UCallExpression),而方法引用属于另一种UAST节点类型——UMethodReferenceExpression(在较新的Lint版本中也可能是UCallableReference)。你需要扩展Detector的逻辑,同时处理这种节点类型。

具体步骤如下:

  1. 扩展Detector的适用UAST类型:
    重写getApplicableUastTypes方法,添加UMethodReferenceExpression::class.java,让Detector能接收这类节点的回调。

  2. 添加方法引用的处理逻辑:
    实现visitUastNode方法,在其中判断当前方法引用是否指向目标类(io.reactivex.Emitter)的onError方法。

修改后的Detector代码如下:

class RxOnErrorDetector : Detector(), Detector.UastScanner {
    // 保留原有的直接方法调用检测逻辑
    override fun getApplicableMethodNames() = listOf("onError")
    override fun visitMethod(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        if (context.evaluator.isMemberInClass(method, "io.reactivex.Emitter")) {
            context.report(ISSUE_ON_ERROR_CALL, node, context.getNameLocation(node), "onError method was called.")
        }
    }

    // 添加方法引用的检测逻辑
    override fun getApplicableUastTypes() = listOf(UMethodReferenceExpression::class.java)
    override fun visitUastNode(context: JavaContext, node: UElement) {
        val methodRef = node as UMethodReferenceExpression
        // 获取引用的方法,处理可能的空值
        val resolvedMethod = methodRef.resolve() as? PsiMethod ?: return
        // 判断是否是Emitter类的onError方法
        if (context.evaluator.isMemberInClass(resolvedMethod, "io.reactivex.Emitter") && resolvedMethod.name == "onError") {
            context.report(
                ISSUE_ON_ERROR_CALL,
                node,
                context.getNameLocation(node),
                "onError method reference was used."
            )
        }
    }
}

关键说明

  • UMethodReferenceExpression是UAST中表示方法引用的节点类型,比如e::onError就会被解析为这个类型。
  • 调用resolve()方法可以获取到引用对应的实际PsiMethod,之后就可以用和直接调用检测相同的逻辑判断是否是目标方法。
  • 必须处理resolve()返回null的情况,避免空指针异常。

内容的提问来源于stack exchange,提问作者Robertas Setkus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:37:40