我想写一个lint规则来捕捉RxJava2函数的结果没有被使用的地方。例如:在RxJava2中,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 UASTPSI APIs来计算结果是否被使用。这是我目前的规则。
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
.
据我所知。node.resolve()
常常回空