首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >分析方法中的变量。JavaParser/ANTLR或其他什么?

分析方法中的变量。JavaParser/ANTLR或其他什么?
EN

Stack Overflow用户
提问于 2012-11-26 11:40:15
回答 3查看 2.4K关注 0票数 4

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-28 14:42:20

谢谢你们。您的两个答案都将我引向了使用JAVAPARSER中的AST实现来解决这个问题的方向。下面是帮助其他人的代码片段

代码语言:javascript
运行
复制
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);

        }
    }
}

实例化类->

代码语言:javascript
运行
复制
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

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

谢谢你们,贾斯米特

票数 3
EN

Stack Overflow用户

发布于 2012-11-26 13:12:15

为了完成查找变量用法的任务,带有ANTLR的解析器单元也应该生成AST。我几乎可以肯定你可以找到准备好的AST构建器,但不知道在哪里。

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

票数 2
EN

Stack Overflow用户

发布于 2012-11-26 13:52:26

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

只要编译器在你的类文件中实际记录了这个信息,你就可以执行“反射”操作来获得它。只要这样的信息存在于.class文件中,您就可以使用类文件字节码处理器来访问它,比如Kaigorodov的答案中提到的那些。

ANTLR有用于Java的语法,但我不相信有任何对符号表构造的支持。您无法自己伪造这一点;Java的规则太复杂了。您也许能够扩展ANTLR解析器来完成此任务,但这将是一项大量的工作;“Java的规则太复杂了”。

我知道Java编译器提供了对其内部结构的某种名称/类型的准确访问;您也许能够使用它。

我们的DMS软件再工程工具包具有完整的Java解析器,具有名称和类型解析功能,可用于此目的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13558373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档