使用谷歌闭包编译器来解析JavaScript源码

时间:2017-02-24 03:15:04

标签: javascript google-closure-compiler

我想使用google closure编译器解析给定的ES6源文件,以便构建一个自定义的面向对象的'该计划的代表。此表示将包括源文件中的所有类以及这些类中包含的方法和变量的详细信息。我已经为使用Antlr的Java程序完成了这项任务 - 一旦你有一个合适的grammar,你就可以为任何想要的语法规则(类声明,方法声明等)注册进入和退出监听器......这使得实施相当直接。如果能够使用谷歌闭包编译器解析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类只输出处理的每个Node的类型和限定名称,如下所示:

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`

我很感激对此输出的解释,因为排序和空值对我来说没有任何意义,以及有关如何解决原始问题的任何一般指导。

2 个答案:

答案 0 :(得分:0)

您将获得空值,因为scenario 'can upvote just one time', js: true do first('a#question-upvote').click sleep 1 expect(first('div#question-score').text).to eq '1' first('a#question-upvote').click sleep 1 expect(first('div#question-score').text).to eq '1' end 仅用于名称节点。这将包括变量名称,函数名称,类名称和属性。它不会为大多数AST节点类型打印出有意义的数据。

答案 1 :(得分:0)

以下代码打印出给定JavaScript程序中的所有方法和类,并概述了使用Google Closure-Compiler的Java API分析JavaScript代码的基本方法,有关详细信息,请参阅this post我写的

首先,我们需要扩展AbstractShallowCallback类,它提供了一种迭代解析树中节点的方法。我们为visit方法提供了一个实现,如果它是我们感兴趣的节点,它将输出Node的值。

map

接下来,我们初始化编译器并在给定的JavaScript源文件上运行我们创建的JavaScript分析器。

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

在以下源文件上运行以上代码:

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