【问题标题】:How to check if the result of an expression is used in a custom Android lint rule如何检查表达式的结果是否用于自定义 Android lint 规则
【发布时间】:2018-09-14 03:46:59
【问题描述】:

我正在尝试编写一个 lint 规则来捕获 RxJava2 函数的结果无论如何都不使用的地方。例如:

final Observable<String> observable = getObservable();
observable.subscribe(this::onSuccess, this::onError);

在 RxJava2 中,subscribe 函数返回一个 Disposable,如果程序/类实例以某种方式“完成”以防止内存泄漏,则应使用该函数取消订阅。如果发现任何此类事件,我希望我的构建失败。

这个特殊的方法(以及我感兴趣的所有其他方法)都用io.reactivex.annotations.CheckReturnValue注释:

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {
    return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}

我的计划是编写一个自定义 lint 规则:

  • 搜索返回带有io.reactivex.annotations.CheckReturnValue 注释的方法结果的表达式
  • 将搜索过滤到只有结果从未使用过的表达式

例如,以下是一些不应失败的情况:

final CompositeDisposable compositeDisposable = new CompositeDisposable();
// Result of subscribe passed into another function
compositeDisposable.add(observable.subscribe(this::onSuccess, this::onError).dispose());

// Result of subscribe stored in a variable
final Disposable disposable = observable.subscribe(this::onSuccess, this::onError);

// Result of subscribe used
observable.subscribe(this::onSuccess, this::onError).dispose();

我已经设法编写了一个 lint 规则来查找调用表达式的实例,其中结果用 CheckReturnValue 注释,但我正在努力弄清楚如何使用 JetBrains UAST/PSI API 来确定是否结果被使用。到目前为止,这是我的规则:

class RxJava2CheckReturnValueMethodNotAssigned : Detector(), Detector.UastScanner {
    override fun getApplicableUastTypes() = listOf(UCallExpression::class.java)

    override fun createUastHandler(context: JavaContext) = CheckReturnValueVisitor(context)

    class CheckReturnValueVisitor(private val context: JavaContext) : UElementHandler() {

        override fun visitCallExpression(node: UCallExpression) {
            val method = node.resolve() ?: return
            if (!isCheckReturnValueAnnotatedMethod(method)) {
                return
            }
            if (!isResultOfCallUsed(node)) {
                return
            }

            reportIssue(node)
        }

        private fun isCheckReturnValueAnnotatedMethod(method: PsiMethod): Boolean {
            return context.evaluator.getAllAnnotations(method, true)
                .any { "io.reactivex.annotations.CheckReturnValue" == it.qualifiedName }
        }

        private fun isResultOfCallUsed(node: UCallExpression): Boolean {
            // Need to check is the result of the expression is used in some way
            return false
        }

        private fun reportIssue(node: UCallExpression) {
            // SNIP...
        }
    }
}

这目前不起作用,因为它报告了带有 CheckReturnValue 注释的任何函数的所有用法。

【问题讨论】:

  • Android 的 Lint 已经做到了?
  • @nhaarman 它确实出现在 Android Studio 中,但我不知道如何将严重性升级到错误级别,或者至少在 lint 输出文件中生成它。关于如何做到这一点的任何想法?
  • 如果您只是想提高严重性级别,您可以在您的lint.xml 文件中添加类似&lt;issue id="CheckReturnValue" severity="error" /&gt; 的内容

标签: android kotlin rx-java2 jetbrains-ide lint


【解决方案1】:

据我所知,node.resolve() 经常返回 null

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 2021-03-17
    • 2013-05-20
    • 2015-12-13
    • 2019-12-17
    • 2018-01-10
    • 2014-10-30
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多