2012-11-26 72 views
4

我正在寫一個Java代碼分析代碼片段,它將查找方法中變量的用法。 (具體來說,一個全局類變量在一個方法中被讀寫的次數)。這可以使用JavaParser完成嗎?會有人有任何其他建議嗎?是否有人知道如何計算班級指標?他們可能處理類似的事情。分析方法中的變量。 JavaParser/ANTLR還是別的?

回答

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); 

     } 
    } 
} 

實例化類--->

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

+0

現在你與它的工作,你能告訴我,如果你有機會獲得一個類型的'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解析器,與名稱和類型的分辨率,並且可以用於這一目的。