TypeScript:获取语法树

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20187928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 02:52:30  来源:igfitidea点击:

TypeScript: get syntax tree

typescriptabstract-syntax-tree

提问by bukvaG

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 (Esprima Parserexample)

我读过“整个互联网”,但找不到任何关于从 TypeScrypt 源获取语法树(就像在 Esprima 中一样)的例子。我的意思是我怎么能得到这样的对象(Esprima Parser示例)

{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "answer"
                    },
                    "init": {
                        "type": "BinaryExpression",
                        "operator": "*",
                        "left": {
                            "type": "Literal",
                            "value": 6,
                            "raw": "6"
                        },
                        "right": {
                            "type": "Literal",
                            "value": 7,
                            "raw": "7"
                        }
                    }
                }
            ],
            "kind": "var"
        }
    ]
}

from javascript code

来自 javascript 代码

var answer = 6 * 7;

only for TypeScript source text?

仅适用于 TypeScript 源文本?

P.S. I hope very much for your help, because I do not want to write your own terrible bicycle)

PS非常希望对你有所帮助,因为我不想写你自己的可怕的自行车)

P.P.S. I think the lib files typescript.ts(.js) and typescriptServices.ts(.js) to help me, but I do not know how :(

PPS 我认为 lib 文件 typescript.ts(.js) 和 typescriptServices.ts(.js) 可以帮助我,但我不知道如何:(

Solved

解决了

Thanks a lot to the user Steve Fenton. Here is my code, if anyone interested in:

非常感谢用户史蒂夫芬顿。这是我的代码,如果有人感兴趣:

// uses
var typeScriptLS =  new Harness.TypeScriptLS();
var ServicesFactory = new Services.TypeScriptServicesFactory();
var serviceShim = ServicesFactory.createLanguageServiceShim(typeScriptLS);

// add lib.d.ts
var _libText = window.document.getElementById('lib.d.ts').innerText;
typeScriptLS.addScript('lib.d.ts', _libText.replace(/\r\n?/g,"\n"), true);

// add greeter.ts
var _sourceText = window.document.getElementById('greeter.ts').innerText;
typeScriptLS.addScript('greeter.ts', _sourceText.replace(/\r\n?/g,"\n"), true);

// script name
var _scriptName = 'greeter.ts';
// get syntax tree
var _st = serviceShim.languageService.getSyntaxTree(_scriptName);
//console.log(_st);
console.log(JSON.stringify(_st, "", 2));

采纳答案by Fenton

This question came up before back in September.

这个问题早在九月份就被提出来了。

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

目前没有什么可以为您做到这一点 - 没有getSyntaxTree可以调用的神奇方法可以做到这一点。

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.

不过,TypeScript 编译器是开源的 - 并且完全用 TypeScript 编写,因此您可以扫描它以找出是否可以使用/添加句柄。

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 Esprimaor SpiderMonkey.

或者,使用EsprimaSpiderMonkey从已编译的 JavaScript(这是将在运行时实际执行的代码)中获取语法树。

回答by Ryan Cavanaugh

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:

TypeScript 解析器不会直接生成那样的树,但您仍然可以使用它的对象模型来做各种事情。例如,我们在一些工具中使用它来进行语法转换以进行测试。以下是可用于打印语法树的片段:

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

回答by cancerbero

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

使用 recast 和 babylon@next 是可能的。尽管您必须相信这些技术定义的用于表示 TypeScript 代码的语法 AST 并且它们会保持最新状态 - 因为 TypeScript 具有按版本发布的新语言功能(短时间) - 不像其他语言(JavaScript ) 你有明确定义的版本并以标准发布 - 所以如果你的用户开始使用新的语言功能,这些技术(我猜巴比伦)应该保持最新,否则解析将失败

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

回答by Andzej Maciusovic

I found recastto be working very good. Example:

我发现recast效果很好。例子:

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

这将输出所有需要的信息和事件 TypeAnnotation,所以这个库真的很棒:)

[
   {
      "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
      }
   }
]