为Android-Lint编写自定义规则

时间:2013-05-25 05:57:26

标签: android-lint

Q(tldr;):如何使用JavaScanner中的android-lint来检查特定字符串作为参数的特定函数调用是否已被包围一个try / catch块。

详细信息:我已经在官方网站上完成了android-lint教程,并且已经浏览了现有lint-checks的来源。但是,我似乎无法掌握这种基于AST的JavaScanner解析的工作流程。我想要实现的是捕获一个设置特定属性并用try / catch块包围它的函数。例如:

MyPropertySettings.set("SOME_PROPERTY", "SOME_VAL"); 

不应该触发lint规则,但是:

MyPropertySettings.set("SOME_SENSITIVE_PROPERTY", "SOME_VAL"); 

应该因为它没有被SetPropertyException的try / catch块包围。我不想将try / catch引入函数本身,因为它只在非常罕见的情况下抛出异常(并且函数的内部基于一些反射mojo)。

对于这个问题,即使工作流程/提示也没问题。如果我能够完成前几个步骤,我可能会更好地掌握它。

更新:

经过一些研究后,我发现我需要在set中设置上面的getApplicableMethodNames()函数,然后以某种方式读取该函数的属性以决定是否应用该检查。那部分应该很容易。

周围的尝试/捕获将更加困难,我收集我需要做一些“流量分析”。现在问题是怎么回事。

2 个答案:

答案 0 :(得分:2)

嗯,与getApplicableMethodNames()方法一起,您需要覆盖visitMethod()函数。您将获得MethodInvocationNode。只需使用node.astArguments()函数获取调用中传递的参数。这将返回一个参数列表,您可以使用StrictListAccessor进行迭代。检查传递的参数以及是否符合您的条件,运行循环并继续计算调用节点的父节点,直到找到try节点。如果它是try节点,那么您可以使用node.astCatches()获取捕获列表。扫描列表并找到相应的例外。如果没有找到,请报告。

答案 1 :(得分:1)

你可以像这样编码: 检查它是否被try / catch包围:

Player.new

}

在此之前,您必须通过覆盖来定义特定方法:

@Override
public void visitMethod(JavaContext context, AstVisitor visitor, MethodInvocation node) {
    // check the specified class that invoke the method
    JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) context.resolve(node);
    JavaParser.ResolvedClass clzz = method.getContainingClass();
    boolean isSubClass = false;
    // sSupportSuperType = {"class name"};
    for (int i = 0; i < sSupportSuperType.length; i++) {
        if (clzz.isSubclassOf(sSupportSuperType[i], false)) {
            isSubClass = true;
            break;
        }
    }
    if (!isSubClass) return;
    // check if surrounded by try/catch
    Node parent = node;
    while (true) {
        Try tryCatch = context.getParentOfType(parent, Try.class);
        if (tryCatch == null) {
            break;
        } else {
            for (Catch aCatch : tryCatch.astCatches()) {
                TypeReference catchType = aCatch.astExceptionDeclaration().astTypeReference();
            }
            parent = tryCatch;
        }
    }
    // get the arguments string
    String str = node.astArguments().first().toString();
    if (!str.startsWith("\"SOME_PROPERTY\"")) {
        context.report(ISSUE, node, context.getLocation(node), "message");
    }