4

我正在编写一个 java 代码分析片段,它将找出方法中变量的使用。(具体来说,一个全局类变量在一个方法中被读写的次数)。这可以使用 JavaParser 完成吗?有人有其他建议吗?有谁知道类指标是如何计算的?他们可能处理类似的事情。

4

3 回答 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

我很清楚字节码处理器会更有效率,并且会比我希望的更好。但考虑到时间限制,这个选项最适合我。

谢谢大家,贾斯米特

于 2012-11-28T06:42:19.980 回答
2

要完成查找变量用法的任务,带有 ANTLR 的解析器也应该生成 AST。我几乎可以肯定您可以找到现成的 AST 构建器,但不知道在哪里。

另一种方法是使用ASMBCEL或其他类文件分析器来分析类文件。我认为这更容易,而且工作得更快。此外,它也适用于其他 jvm 语言(例如 Scala)。

于 2012-11-26T05:12:14.987 回答
2

要询问有关变量读取是否为“全局”的问题,您需要一个完整的 Java 编译器前端,它可以解析代码、构建符号表和相关类型信息。

如果编译器实际上已经在你的类文件中记录了这些信息,你也许可以执行“反射”操作来获取它。如果此类信息存在于 .class 文件中,您可以使用类文件字节码处理器访问它,例如 Kaigorodov 的答案中提到的那些。

ANTLR 有 Java 语法,但我不相信任何对符号表构造的支持。你不能自己伪造这个;Java 的规则太复杂了。您也许可以扩展 ANTLR 解析器来执行此操作,但这将是很多工作;“Java 的规则太复杂了”。

我了解 Java 编译器提供了对其内部结构的某种名称/类型的准确访问;你也许可以使用它。

我们的 DMS Software Reengineering Toolkit 具有完整的 Java 解析器,具有名称和类型解析,可用于此目的。

于 2012-11-26T05:52:25.700 回答