TypeScript: obtener árbol de sintaxis
abstract-syntax-tree (4)
El analizador de TypeScript no produce directamente un árbol como ese, pero aún puede usar su modelo de objetos para hacer todo tipo de cosas. Lo usamos en algunas herramientas para hacer transformaciones de sintaxis con fines de prueba, por ejemplo. Aquí hay un fragmento que puede usar para imprimir el árbol de sintaxis:
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);
Había leído "Internet completo", pero no encuentro ningún ejemplo sobre cómo obtener el árbol de sintaxis (como en Esprima) desde la fuente TypeScrypt. Me refiero a cómo puedo obtener un objeto como este (ejemplo de 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"
}
]
}
del código javascript
var answer = 6 * 7;
solo para texto fuente de TypeScript?
PD. Espero mucho tu ayuda, porque no quiero escribir tu propia bicicleta terrible)
PPS Creo que los archivos lib mecanografían .txt (.js) y typescriptServices.ts (.js) para ayudarme, pero no sé cómo :(
Resuelto
Muchas gracias al usuario Steve Fenton. Aquí está mi código, si alguien está interesado en:
// 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));
Encontré la recast para estar funcionando muy bien. Ejemplo:
var recast = require(''recast'');
var ast = recast.parse(`var answer = 6 * 7;`);
console.log(ast);
Esto generará toda la información necesaria y evento TypeAnnotation, por lo que esta lib es realmente increíble :)
[
{
"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
}
}
]
Esta pregunta surgió antes de septiembre .
Actualmente, no hay nada que lo haga por usted, no hay getSyntaxTree
método mágico getSyntaxTree
para llamar que lo haga.
Sin embargo, el compilador de TypeScript es de código abierto y está escrito completamente en TypeScript para que pueda escanearlo y descubrir si hay algo que pueda usar / agregar un identificador.
El lado bueno de esto es que tiene una gran oportunidad para lanzar su trabajo como un proyecto de código abierto ya que a juzgar por las votaciones en las dos preguntas, hay algo de demanda para esto.
Alternativamente, tome el árbol de sintaxis del JavaScript compilado (que es el código que realmente se ejecutará en tiempo de ejecución) usando Esprima o SpiderMonkey .
Usando refundición y babylon @ siguiente es posible. Aunque tendrá que confiar en la sintaxis definida por estas tecnologías para representar el código AST de TypeScript y que se mantendrá actualizado, ya que TypeScript tiene nuevas características de idioma por versión (período corto de tiempo), no es como otros idiomas (JavaScript ) donde tienes versiones bien definidas y publicadas en un estándar, por lo que si tus usuarios comienzan a usar nuevas características de idioma, estas tecnologías (supongo que Babylon) deben mantenerse actualizadas o el análisis fracasará.
// 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)}
`);