我正在编写一个java代码分析代码段,它将在方法中找出变量的用法。 (具体而言,在方法中读取和写入全局类变量的次数)。可以使用JavaParser完成吗?有人会有任何其他建议吗?有没有人知道如何计算课程指标?他们可能会处理类似的事情。
答案 0 :(得分:2)
要完成查找变量用法的任务,使用ANTLR的解析器buld也应该生成AST。我几乎可以肯定你可以找到准备好的AST构建器,但不知道在哪里。
另一种方法是使用ASM,BCEL或其他类文件分析器分析类文件。我认为它更容易,而且工作速度更快。此外,它适用于其他jvm语言(例如Scala)。
答案 1 :(得分:2)
要询问变量读取是否为“全局”,您需要一个完整的Java编译器前端,它解析代码,构建符号表和相关的类型信息。
如果编译器已经在您的类文件中实际记录了这些信息,您可以执行“反射”操作来获取它。如果这些信息存在于.class文件中,您可以使用类文件字节码处理器访问它,例如Kaigorodov的答案中提到的那些。
ANTLR有Java语法,但我不相信对符号表构造的任何支持。 你不能自己假装; Java的规则太复杂了。您可以扩展ANTLR解析器来执行此操作,但这将是很多工作; “Java的规则过于复杂”。
我理解Java编译器提供某种名称/类型的内部结构的准确访问;你或许可以使用它。
我们的DMS软件重组工具包具有完整的Java解析器,具有名称和类型解析,可用于此目的。
答案 2 :(得分:2)
谢谢你们。你的答案都引导我使用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);
}
}
}
实例化班级---&gt;
CatchNameExpr nameExp = new CatchNameExpr(classVariables);
nameExp.visit(classCompilationUnit, null);
以类似的方式,您可以访问AST以获取以下表达式,语句,条件等
我很清楚字节码处理器会更高效,并且可以比我希望的更好地完成工作。但考虑到时间限制,这个选项最适合我。
谢谢你们, Jasmeet