2017-02-24 121 views
0

我想解析給定的ES6源文件使用谷歌封閉編譯器,以建立一個自定義的「面向對象」的程序表示。這種表示將包括源文件中所有類的的詳細信息以及這些類中包含的方法和變量。我已經完成了Java程序的這項任務,我使用了Antlr - 一旦你有合適的grammar,你可以爲任何需要的語法規則(類聲明,方法聲明等等)註冊進入和退出監聽器,這使得實現相當簡單。我將不勝感激任何幫助能夠使用谷歌封閉編譯器解析JavaScript代碼,以提取有關源代碼的類似信息。使用谷歌封閉編譯器來解析JavaScript源

到目前爲止,我有以下的代碼,這將解析給定的JavaScript源文件:

Compiler compiler = new Compiler(); 
CompilerOptions options = new CompilerOptions(); 
options.setIdeMode(true); 
compiler.initOptions(options); 
Node root = new JsAst(SourceFile.fromCode(file.name(), file.content())).getAstRoot(compiler); 
NodeTraversal.traverseEs6(compiler, root, new JavaScriptParsePass()); 

的JavaScriptParsePass類簡單地輸出處理的每個節點的類型和合格的名稱,它看起來像如下:

public class JavaScriptParsePass extends AbstractPostOrderCallback implements CompilerPass { 

    @Override 
    public void process(Node externs, Node root) { 
    } 

    @Override 
    public void visit(NodeTraversal t, Node n, Node parent) { 
     System.out.println(n.getType() + ": " + n.getQualifiedName()); 
    } 
} 

在輸入運行該程序: class Model { constructor(properties) { this.properties = properties; }

生成輸出:

38: Model 
124: null 
38: null 
38: properties 
83: null 
42: this 
40: null 
33: this.properties 
38: properties 
86: null 
130: null 
125: null 
105: null 
160: null 
159: null 
158: null 
132: null` 

我希望這個輸出作爲排序的解釋和空不就如何解決原有問題的任何一般性指導一起道理給我。

回答

0

由於n.getQualifiedName()僅適用於名稱節點,因此您將得到空值。這將包括變量名稱,函數名稱,類名稱和屬性。它不會爲大多數AST節點類型打印出有意義的數據。

+0

我怎麼會想出一個給定的節點是否是一個類名稱,函數名稱或變量名稱?另外,一旦我找到了一個類名節點,我怎麼知道我們何時完成了解析該節點在語義上表示的類?是否有一個特殊的「退出」節點,我可以尋找或有另一種方式來做到這一點? –

+0

你必須把AST看作一個整體。編譯器有很多通過分析AST的例子。以下是一個:https:// github。COM /谷歌/閉合編譯器/斑點/主/ SRC/COM /谷歌/ JavaScript的/ jscomp/ProcessCommonJSModules.java#L257 –

0

以下代碼打印出給定JavaScript程序中的所有方法和類,並概述使用Google Closure-Compiler的Java API分析JavaScript代碼的基本方法,更多詳細信息請參閱我寫的this post

首先,我們需要擴展AbstractShallowCallback類,它提供了一種方法來遍歷解析樹中的節點。我們提供的訪問方法,將輸出節點的價值的實現,如果它是我們感興趣的一個節點。

public class JavaScriptAnalyzer extends AbstractShallowCallback { 

@Override 
    public void visit(NodeTraversal t, Node n, Node parent) { 
     if (n.isClass()) { 
      System.out.println(n.getFirstChild().getString()); 
     } 
     if (n.isMemberFunctionDef() || n.isGetterDef() || n.isSetterDef()) { 
      System.out.println(n.getString()); 
     } 
     if (n.isFunction()) { 
      System.out.println(n.getFirstChild().getString()); 
     } 
     // there is more work required to detect all types of methods that 
     // has been left out for brevity... 
    } 
} 

接下來我們初始化一個編譯器和一個給定的JavaScript源文件運行我們創建的JavaScript分析。

public void parse(String jsFileContent, String jsName) throws Exception { 
    Compiler compiler = new Compiler(); 
    CompilerOptions options = new CompilerOptions(); 
    options.setIdeMode(true); 
    compiler.initOptions(options); 
    Node root = new JsAst(SourceFile.fromCode(jsName, jsFileContent)).getAstRoot(compiler); 
    JavaScriptAnalyzer jsListener = new JavaScriptAnalyzer(); 
    NodeTraversal.traverseEs6(compiler, root, jsListener); 
} 

以下源文件運行上面的代碼:

class Polygon { 
    constructor(height, width) {} 
    logWidth() {} 
    set width(value) {} 
    get height(value) {} 
} 

主要生產如預期的輸出如下:

constructor 
logWidth 
width 
height 
Polygon