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

Java 识别语句/行中使用的变量,java,unit-testing,parsing,abstract-syntax-tree,javaparser,Java,Unit Testing,Parsing,Abstract Syntax Tree,Javaparser,给定一个方法,我想识别未使用的变量。 我目前看到的格式保证每个方法的最后一行都有一个assert语句 我使用JavaParser解析每个方法,列出语句,还列出该方法中使用的所有变量 如何检索上一条语句中使用的所有变量 private static class MethodVisitor extends VoidVisitorAdapter<Object> { @Override public void visit(MethodDeclaration n, Objec

给定一个方法,我想识别未使用的变量。 我目前看到的格式保证每个方法的最后一行都有一个assert语句

我使用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();
    }
}
私有静态类MethodVisitor扩展了VoidVisitorAdapter{
@凌驾
公共无效访问(方法声明n,对象参数){
System.out.println(“方法:+n.getName());
BlockStmt body=n.getBody();
List语句=body.getStmts();
新的VariableVisitor().visit(n,null);
语句lastsmt=statements.get(statements.size()-1);
for(报表st:报表){
System.out.println(“语句:+st.toString());
}
System.out.println(“\n\n”);
}
}
私有静态类VariableVisitor扩展了VoidVisitorAdapter{
@凌驾
公共无效访问(VariableDeclarationExpr n,对象参数){
List myVars=n.getVars();
for(变量声明器变量:myVars){
System.out.println(“变量名:”+vars.getId().getName());
}
System.out.println();
}
}

您可以在这方面获得不同的方法:

  • 您只需获取该方法的主体,递归地让所有子级查找all NameExpr,然后检查名称是否与某些变量对应,并将其标记为已使用
  • 您可以使用which为您查找所引用内容的名称expr
  • 现在,第一个1的问题是它并不总是给你正确的答案。为什么?因为您可以将其他东西命名为变量,而您没有区分此类情况的逻辑

    例如:

    void foo(int i) {
       int i;
       {
          int i;
          {
              int j = i;
          }
       }
    }
    
    这里我有不同的东西叫做“我”。所以,如果你想得到精确的答案,你需要在逻辑中考虑这一点。JavaParser不知道哪些名称引用什么,因为它生成一个抽象语法树。名称解析是以后发生的事情,它不是JavaParser的一部分

    但是,名称解析是JavaSymbolSolver的一部分。可以考虑使用JavaPaServer的扩展来计算类型和求解符号。这意味着有一个依赖关系,所以你需要考虑它是否是你想要的。
    免责声明:我是JavaParser的贡献者,也是JavaSymbolSolver的负责人。我想知道的是:你为什么要重新发明轮子?有一些工具可以为您执行此类检查。见鬼,您甚至可以调优javac,为未使用的变量提供警告。那么,为什么要创建自己的解决方案,而这种解决方案总是伴随着不完全正确的风险?