我读过“整个互联网”,但找不到任何关于从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"
}
]
}
来自javascript代码
var answer = 6 * 7;
仅适用于TypeScript源文本?
P.S。我非常希望得到你的帮助,因为我不想写自己糟糕的自行车)
P.P.S。我认为lib文件typescript.ts(.js)和typescriptServices.ts(.js)对我有所帮助,但我不知道如何:(
解决
非常感谢用户Steve Fenton。 这是我的代码,如果有人对此感兴趣:
// 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));
答案 0 :(得分:16)
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);
答案 1 :(得分:7)
这个问题出现在back in September之前。
目前没有任何东西会为您执行此操作 - 没有魔法getSyntaxTree
方法可以执行此操作。
TypeScript编译器虽然是开源的,但完全用TypeScript编写,因此您可以扫描它以查明是否有可以使用/添加句柄的内容。
最重要的是,你有很大的机会将你的工作作为一个开源项目发布,从这两个问题的投票来判断,对此有一些需求。
或者,使用Esprima或SpiderMonkey从已编译的JavaScript(即将在运行时实际执行的代码)中获取语法树。
答案 2 :(得分:0)
我发现recast工作得非常好。例如:
var recast = require('recast');
var ast = recast.parse(`var answer = 6 * 7;`);
console.log(ast);
这将输出所有需要的信息和事件TypeAnnotation,所以这个lib非常棒:)
[
{
"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
}
}
]
答案 3 :(得分:0)
可以使用重铸和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)}
`);