TypeScript: get syntax tree

后端 未结 4 1437
悲&欢浪女
悲&欢浪女 2020-12-12 20:39

I had read \"whole internet\", but can\'t find any examples about getting syntax tree (just like in Esprima) from TypeScrypt source. I mean how can i get object like this (E

相关标签:
4条回答
  • 2020-12-12 21:11

    The TypeScript parser doesn't directly produce a tree like that, but you can still use its object model to do all sorts of things. We use it in some tools to do syntax transforms for testing purposes, for example. Here's a snippet that you can use to print the syntax tree:

    import ts = require('typescript');
    
    const code = "enum { x = 1 }"
    const sc = ts.createSourceFile('x.ts', code, ts.ScriptTarget.Latest, true);
    
    let indent = 0;
    function print(node: ts.Node) {
        console.log(new Array(indent + 1).join(' ') + ts.SyntaxKind[node.kind]);
        indent++;
        ts.forEachChild(node, print);
        indent--;
    }
    
    print(sc);
    
    0 讨论(0)
  • 2020-12-12 21:12

    This question came up before back in September.

    There isn't currently something that will do this for you - there is no magic getSyntaxTree method to call that will do this.

    The TypeScript compiler is open-source, though - and written entirely in TypeScript so you can scan it to find out if there is something you can use / add a handle to.

    The up-side of this is that you have a big opportunity to release your work as an open-source project as judging by the up-votes on the two questions, there is some demand for this.

    Alternatively, grab the syntax tree from the compiled JavaScript (which is the code that will actually execute at runtime) using Esprima or SpiderMonkey.

    0 讨论(0)
  • 2020-12-12 21:25

    I found recast to be working very good. Example:

    var recast = require('recast');
    var ast = recast.parse(`var answer = 6 * 7;`);
    console.log(ast);
    

    This will output all needed information and event TypeAnnotation, so this lib is really amazing :)

    [
       {
          "type": "VariableDeclaration",
          "declarations": [
             {
                "type": "VariableDeclarator",
                "id": {
                   "type": "Identifier",
                   "name": "answer",
                   "typeAnnotation": {
                      "type": "TypeAnnotation",
                      "typeAnnotation": {
                         "type": "NumberTypeAnnotation",
                         "loc": {
                            "start": {
                               "line": 1,
                               "column": 12
                            },
                            "end": {
                               "line": 1,
                               "column": 18
                            },
                            "lines": {},
                            "indent": 0
                         }
                      },
                      "loc": {
                         "start": {
                            "line": 1,
                            "column": 10
                         },
                         "end": {
                            "line": 1,
                            "column": 18
                         },
                         "lines": {},
                         "indent": 0
                      }
                   },
                   "loc": {
                      "start": {
                         "line": 1,
                         "column": 4
                      },
                      "end": {
                         "line": 1,
                         "column": 18
                      },
                      "lines": {},
                      "indent": 0
                   }
                },
                "init": {
                   "type": "BinaryExpression",
                   "operator": "*",
                   "left": {
                      "type": "Literal",
                      "value": 6,
                      "raw": "6",
                      "loc": {
                         "start": {
                            "line": 1,
                            "column": 21
                         },
                         "end": {
                            "line": 1,
                            "column": 22
                         },
                         "lines": {},
                         "indent": 0
                      }
                   },
                   "right": {
                      "type": "Literal",
                      "value": 7,
                      "raw": "7",
                      "loc": {
                         "start": {
                            "line": 1,
                            "column": 25
                         },
                         "end": {
                            "line": 1,
                            "column": 26
                         },
                         "lines": {},
                         "indent": 0
                      }
                   },
                   "loc": {
                      "start": {
                         "line": 1,
                         "column": 21
                      },
                      "end": {
                         "line": 1,
                         "column": 26
                      },
                      "lines": {},
                      "indent": 0
                   }
                },
                "loc": {
                   "start": {
                      "line": 1,
                      "column": 4
                   },
                   "end": {
                      "line": 1,
                      "column": 26
                   },
                   "lines": {},
                   "indent": 0
                }
             }
          ],
          "kind": "var",
          "loc": {
             "start": {
                "line": 1,
                "column": 0
             },
             "end": {
                "line": 1,
                "column": 27
             },
             "lines": {},
             "indent": 0
          }
       }
    ]
    
    0 讨论(0)
  • 2020-12-12 21:29

    Using recast and babylon@next is possible. Although you will have to trust in the syntax defined by these technologies for representing TypeScript code AST and that they will keep up to date - since TypeScript has new language features release by release (short period of time) - is not like other languages (JavaScript) where you have well defined versions and released in a standard - so if your users start using new language features these technologies (I guess babylon) should keep up to date or the parsing will fail

    // npm install recast babylon@next
    const source = `
    interface I {
      color: string
    }
    class C implements I{
      color: string='blue'
    }
    `
    const recast = require('recast')
    const tsParser = require("recast/parsers/typescript")
    const ast = recast.parse(source, {
      parser: tsParser
    });
    console.log(`
    CODE: 
    
    ${source}
    
    AST: 
    
    ${JSON.stringify(ast)}
    `);
    
    0 讨论(0)
提交回复
热议问题