TypeScript: получить синтаксическое дерево
Я прочитал "весь интернет", но не могу найти примеров получения дерева синтаксиса (как в Esprima) из источника TypeScrypt.
Я имею в виду, как я могу получить объект, подобный этому (пример 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), чтобы помочь мне, но я не знаю, как: (
решаемые
Большое спасибо пользователю Стив Фентону.
Вот мой код, если кто интересуется:
// 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));
Ответы
Ответ 1
Этот вопрос возник до в сентябре.
В настоящее время не существует чего-то, что сделает это для вас - нет волшебного метода getSyntaxTree
для вызова, который сделает это.
Компилятор TypeScript является открытым исходным кодом, но - и полностью написан в TypeScript, поэтому вы можете сканировать его, чтобы узнать, есть ли что-то, что вы можете использовать/добавить дескриптор.
В стороне от этого заключается в том, что у вас есть большая возможность опубликовать свою работу в качестве проекта с открытым исходным кодом, поскольку, судя по громким голосам по двум вопросам, есть определенная потребность в этом.
В качестве альтернативы возьмите дерево синтаксиса из скомпилированного JavaScript (который является кодом, который будет фактически выполняться во время выполнения) с помощью Esprima или SpiderMonkey.
Ответ 2
Парсер 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);
Ответ 3
Я нашел recast, чтобы работать очень хорошо. Пример:
var recast = require('recast');
var ast = recast.parse(`var answer = 6 * 7;`);
console.log(ast);
Это выведет всю необходимую информацию и событие 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
}
}
]