识别语句/行中使用的变量

时间:2016-11-27 19:26:01

标签: java unit-testing parsing abstract-syntax-tree javaparser

给定一种方法我想识别未使用的变量。 我目前正在考虑的格式保证有一个断言语句作为每个方法的最后一行。

我正在使用JavaParser来解析每个方法,列出语句并列出该方法中使用的所有变量。

如何检索上一个语句中使用的所有变量?

private static class MethodVisitor extends VoidVisitorAdapter<Object> {

    @Override
    public void visit(MethodDeclaration n, Object arg) {
        System.out.println("Method: " + n.getName());

        BlockStmt body = n.getBody();
        List<Statement> statements = body.getStmts();

        new VariableVisitor().visit(n, null);

        Statement lastStmt = statements.get(statements.size() - 1);

        for (Statement st : statements) {
            System.out.println("Statement: " + st.toString());
        }
        System.out.println("\n\n");
    }
}

private static class VariableVisitor extends VoidVisitorAdapter<Object> {
    @Override
    public void visit(VariableDeclarationExpr n, Object arg) {
        List<VariableDeclarator> myVars = n.getVars();
        for (VariableDeclarator vars : myVars) {
            System.out.println("Variable Name: " + vars.getId().getName());
        }
        System.out.println();
    }
}

1 个答案:

答案 0 :(得分:3)

您可以采用不同的方法:

  1. 您只需获取方法的主体并递归地让所有子项找到所有NameExpr,然后检查名称是否与某些变量相对应并将其标记为已使用
  2. 您使用JavaSymbolSolver向您发现NameExpr指向的内容
  3. 现在,第一个问题是它并不总能给你正确答案。为什么?因为你可以将其他东西命名为你的变量,而你没有逻辑来区分这些情况

    例如:

    void foo(int i) {
       int i;
       {
          int i;
          {
              int j = i;
          }
       }
    }
    

    这里我有不同的名字叫“我”。因此,如果您想获得准确的答案,则需要在逻辑中考虑这一点。 JavaParser不知道哪些名称引用了什么,因为它生成了一个抽象语法树。名称解析是稍后发生的事情,它不是JavaParser的一部分。

    然而,名称解析是JavaSymbolSolver的一部分。您可以考虑使用JavaParser的这个扩展来计算类型和解码符号。这意味着还有一个依赖项,因此您需要考虑它是否符合您的要求。

    免责声明:我是JavaParser的贡献者,也是JavaSymbolSolver的佼佼者