【发布时间】: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文件中添加类似<issue id="CheckReturnValue" severity="error" />的内容
标签: android kotlin rx-java2 jetbrains-ide lint