com.rx.errorprone.DanglingSubscriptionCheck Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxbase Show documentation
Show all versions of rxbase Show documentation
Error prone checks for RxJava
The newest version!
package com.rx.errorprone;
import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.matchers.Matchers;
import com.google.errorprone.util.ASTHelpers;
import com.rx.errorprone.utils.AbstractReturnValueIgnored;
import com.rx.errorprone.utils.MatcherUtils;
import com.sun.source.tree.ExpressionTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import java.util.Objects;
import static com.google.errorprone.BugPattern.Category.JDK;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.util.ASTHelpers.hasAnnotation;
/** @author [email protected] (Harshit Bangar) */
@AutoService(BugChecker.class)
@BugPattern(
name = "DanglingSubscriptionCheck",
summary = "Subscription should be assigned to a disposable.",
explanation =
"Observable's subscription should be assigned to a disposable for cleanup, otherwise it may lead to a leak",
category = JDK,
severity = WARNING
)
public class DanglingSubscriptionCheck extends AbstractReturnValueIgnored {
private static final Matcher ON_SUBSCRIBE = MatcherUtils.subscribeWithForRx2();
// Check for return type Disposable.
// It is not able to detect correct type in subscribeWith so ON_SUBSCRIBE matcher is combined.
// public final > E subscribeWith(E observer)
private static final Matcher MATCHER =
Matchers.anyOf(
ON_SUBSCRIBE,
new Matcher() {
@Override
public boolean matches(ExpressionTree tree, VisitorState state) {
Type disposableType =
Objects.requireNonNull(state.getTypeFromString("io.reactivex.disposables.Disposable"));
Symbol untypedSymbol = ASTHelpers.getSymbol(tree);
if (!(untypedSymbol instanceof Symbol.MethodSymbol)) {
return false;
}
Symbol.MethodSymbol sym = (Symbol.MethodSymbol) untypedSymbol;
if (hasAnnotation(sym, CanIgnoreReturnValue.class, state)) {
return false;
}
Type returnType = sym.getReturnType();
return ASTHelpers.isSubtype(
ASTHelpers.getUpperBound(returnType, state.getTypes()), disposableType, state);
}
});
@Override
public Matcher super ExpressionTree> specializedMatcher() {
return MATCHER;
}
@Override
public String linkUrl() {
return "https://bitbucket.org/littlerobots/rxlint";
}
}