在方法内分析变量。JavaParser/ANTLR还是其他什么?

4

我正在编写一段Java代码分析片段,用于查找方法中变量的使用情况(具体来说,是全局类变量在方法中被读取和写入的次数)。是否可以使用JavaParser完成这个任务?还有其他推荐吗?有人知道如何计算类度量吗?它们可能涉及类似的内容。

3个回答

3

谢谢大家。你们的回答都让我朝着使用JAVAPARSER中的AST实现解决这个问题的方向前进。下面是一个代码片段,希望能帮助到其他人。

class CatchNameExpr extends VoidVisitorAdapter {
    HashMap<String, ArrayList<Integer>> variableLineNumMap;``
    ArrayList<String> variableList;
    boolean functionParsing = false;
    public CatchNameExpr(ArrayList<String> classVariables) {
        variableList=classVariables;
    }
    public void visit(MethodDeclaration method, Object arg) {
        System.out.println("---------------");
        System.out.println(method.getName());
        System.out.println("---------------");
        variableLineNumMap = new HashMap<String, ArrayList<Integer>>();
        System.out.println();
        functionParsing = true;
        visit(method.getBody(),arg);
        // Analyze lines for variable usage. Add to list of vars after checking if its read or written or unknown.

        functionParsing = false;
    }

    public void visit(NameExpr n, Object arg) {

        if(!functionParsing)
            return;
        //TODO: check if this var was declared above it, as a local var to the func. if yes, return
        ArrayList<Integer> setOfLineNum;

        System.out.println(n.getBeginLine()+" NameExpr " + n.getName());

        if(!variableList.contains(n.getName()) || n.getName().length()==0)
            return;
        if (!variableLineNumMap.containsKey(n.getName()))
        {
            setOfLineNum =   new ArrayList<Integer>();
            setOfLineNum.add(n.getBeginLine());
            variableLineNumMap.put(n.getName(), setOfLineNum);
        }
        else
        {
            setOfLineNum = variableLineNumMap.get(n.getName());
            setOfLineNum.add(n.getBeginLine());
            variableLineNumMap.put(n.getName(), setOfLineNum);

        }
    }
}

实例化该类 --->

CatchNameExpr nameExp = new CatchNameExpr(classVariables);
        nameExp.visit(classCompilationUnit, null);

同样的,您可以访问AST以获取以下表达式、语句、条件等。请点击链接查看详细信息:http://www.jarvana.com/jarvana/view/com/google/code/javaparser/javaparser/1.0.8/javaparser-1.0.8-javadoc.jar!/japa/parser/ast/visitor/VoidVisitorAdapter.html
我了解到字节码处理器会更加有效,比我希望的效果要好。但是考虑到时间限制,这个选项最适合我。
谢谢大家, Jasmeet

既然你已经在使用它,请问你能否告诉我是否以某种方式访问Expression类型?https://stackoverflow.com/questions/28851648/ - towi

2
完成查找变量用法的任务,需要使用ANTLR构建的解析器也要生成AST。我几乎确定你可以找到现成的AST构建器,但不知道在哪里。
另一种方法是使用ASMBCEL或其他类文件分析器来分析类文件。我认为这种方法更容易,速度也更快。此外,它还可以用于其他JVM语言(例如Scala)。

2
要询问一个变量是否是"全局"的,你需要完整的Java编译器前端,其中包括解析代码、构建符号表和相关类型信息。
只要编译器实际在你的类文件中记录了这些信息,你就可以执行"反射"操作来获取它。只要这些信息存在于.class文件中,你就可以使用类文件字节码处理器访问它,例如Kaigorodov答案中提到的那些。
ANTLR有一个Java语法,但我不认为它支持符号表构建。你无法自己伪造这个;Java的规则太复杂了。你可能能够扩展ANTLR解析器来做到这一点,但那将是大量的工作;"Java的规则太复杂了"。
我了解到Java编译器提供了一种名称/类型准确访问其内部结构的方法;你可能可以使用它。
我们的DMS软件重组工具包具有完整的Java解析器,具有名称和类型解析功能,并可用于此目的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接