我正在尝试创建自定义的Lint检查,以便特殊的注释方法必须先确保片段/活动已附加/可见,然后再进行任何工作。
例如
class MyFragment extends Fragment {
@CheckIsActive
void lint_fail() {
// This would throw a lint warning
}
@CheckIsActive
void lint_succeed() {
if(isAdded()) {
// This wouldn't throw a lint warning
}
}
}
为此,我创建了一个IssueRegistry
,@CheckIsActive
批注和以下自定义Detector
类。
public class CheckActiveDetector extends Detector implements Detector.UastScanner {
private static final String CHECK_ACTIVE_ANNOTATION = Constants.ANNOTATIONS_PREFIX + "CheckIsActive";
private static final Implementation IMPLEMENTATION = new Implementation(
CheckActiveDetector.class,
Scope.JAVA_FILE_SCOPE);
public static final Issue ISSUE = Issue.create(
"CheckActive",
"Method should check if the activity/fragment is active",
"This method should ensure the Activity/Fragment is active before continuing",
Category.CORRECTNESS,
9,
Severity.WARNING,
IMPLEMENTATION
);
public CheckActiveDetector() {}
@Nullable
@Override
public List<Class<? extends UElement>> getApplicableUastTypes() {
return Collections.<Class<? extends UElement>>singletonList(UMethod.class);
}
@Nullable
@Override
public UElementHandler createUastHandler(@NotNull final JavaContext context) {
return new UElementHandler() {
@Override
public void visitMethod(@NotNull UMethod node) {
UExpression body = node.getUastBody();
if(body != null && node.findAnnotation(CHECK_ACTIVE_ANNOTATION) != null) {
String methodName = node.getName();
String message = "Overriding method should call `isAdded()"
+ methodName + "`";
Location location = context.getLocation(node);
context.report(ISSUE, node, location, message);
}
}
};
}
}
我一直在努力寻找如何从我现在所处的状态前进,我认为这是进入一种方法并正确检查它是否被注释的状态。我不确定探测器的方法,如何
isAdded()
或为Activity调用了isDestroyed()
有人知道如何进行此操作或知道其中的任何记录吗?看来Google并未在其来源中使用最新的lint版本(例如CallSuper source),因此并没有太大帮助。
谢谢
答案 0 :(得分:0)
我怀疑实际的Lint规则会非常复杂,但是在非常简单的情况下,可以通过以下方式实现:
@Override
public void visitMethod(@NotNull UMethod node) {
if (node.findAnnotation(CHECK_ACTIVE_ANNOTATION) == null) {
return;
}
UExpression body = node.getUastBody();
if (!(body instanceof UBlockExpression)) {
return;
}
List<UExpression> expressions = ((UBlockExpression) body).getExpressions();
UExpression firstExpression = expressions.get(0);
// check if the first expression in method body is 'if' expression
if (!(firstExpression instanceof UIfExpression)) {
// probably it is not okay
return;
}
UExpression condition = ((UIfExpression) firstExpression).getCondition();
if (!(condition instanceof UCallExpression)) {
// isAdded() is a method call, so we need a UCallExpression
// probably not ok
return;
}
if ("isAdded".equals(((UCallExpression) condition).getMethodName())) {
// it is ok
// you can also check argument count and the owner of the method to
// ensure it is the correct one
} else {
// it is not ok
}
}