2017-02-24 2 views
0

Ich möchte eine bestimmte ES6-Quelldatei mit dem Google-Closure-Compiler analysieren, um eine benutzerdefinierte 'objektorientierte' Darstellung des Programms zu erstellen. Diese Darstellung würde Details zu aller Klassen in der Quelldatei und den Methoden und Variablen enthalten, die in diesen Klassen enthalten sind. Ich habe diese Aufgabe für Java-Programme abgeschlossen, wo ich Antlr verwendet habe - sobald Sie eine geeignete grammar haben, können Sie Listener eingeben und beenden für jede gewünschte Grammatikregel (Klassendeklaration, Methodendeklaration, etc ...), die die Implementierung ziemlich geradlinig gemacht . Ich würde jede Hilfe schätzen, die in der Lage ist, JavaScript-Code mit dem Google-Closure-Compiler zu analysieren, um ähnliche Informationen über den Quellcode zu extrahieren.Verwenden von Google Closure-Compiler zum Parsen von Javascript-Quelle

Bisher habe ich den folgenden Code haben, die eine gegebene Javascript Quelldatei analysieren wird:

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

Die JavaScriptParsePass Klasse gibt einfach die Art und qualifizierte Namen jeder Knoten verarbeitet, sieht es wie folgt aus:

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

das Ausführen dieses Programm auf dem Eingang: class Model { constructor(properties) { this.properties = properties; }

Ausgang Produziert:

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` 

würde ich eine Erklärung für diese Ausgabe wie die Bestellung schätzen und nulls mich nicht zusammen mit einer allgemeinen Führung Sinn ergibt, wie das ursprüngliche Problem zu lösen.

Antwort

0

Sie erhalten nulls weil n.getQualifiedName() ist nur für den Namen Knoten bestimmt sind. Dies würde Variablennamen, Funktionsnamen, Klassennamen und Eigenschaften enthalten. Es werden keine aussagekräftigen Daten für die meisten AST-Knotentypen ausgegeben.

+0

Wie würde ich herausfinden, ob ein gegebener Knoten ist entweder eine Klasse Name, Funktionsname oder Variablenname? Wenn ich einen Klassennamenknoten gefunden habe, wie weiß ich dann, wann wir die Klasse, die dieser Knoten semantisch darstellt, analysiert haben? Gibt es einen speziellen "Exit" -Knoten, den ich suchen kann oder gibt es einen anderen Weg, dies zu tun? –

+0

Sie müssen den AST als Ganzes betrachten. Der Compiler hat viele Durchläufe, die den AST analysieren, die gute Beispiele machen. Hier ist eins: https: // github.com/google/schloss-compiler/blob/master/src/com/google/javascript/jscomp/ProzessCommonJSModules.java # L257 –

0

Der folgende Code gibt alle Methoden und Klassen in einem bestimmten JavaScript-Programm aus und beschreibt die grundlegende Methode zur Analyse von JavaScript-Code mithilfe der Java-API des Google Closure-Compilers. Weitere Details finden Sie unter this post.

Zuerst müssen wir die AbstractShallowCallback-Klasse erweitern, die eine Möglichkeit bietet, die Knoten im Parse-Baum zu durchlaufen. Wir bieten eine Implementierung für den Besuch Methode des Knotens Wert, wird ausgegeben, wenn es ein Knoten ist, dass wir interessiert sind.

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... 
    } 
} 

Als nächstes werden wir einen Compiler und führen unser erstellt JavaScript Analyzer auf einem bestimmten JavaScript-Quelldatei zu initialisieren.

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

den obigen Code Laufen auf die folgende Quelldatei:

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

erzeugt die folgende Ausgabe wie erwartet:

constructor 
logWidth 
width 
height 
Polygon 
Verwandte Themen