in src/renderer.ts [240:372]
private dispatch(tree: ts.Node): OTree {
const visitor = this.handler;
// Using a switch on tree.kind + forced down-casting, because this is significantly faster than
// doing a cascade of `if` statements with the `ts.is<NodeType>` functions, since `tree.kind` is
// effectively integers, and this switch statement is hence optimizable to a jump table. This is
// a VERY significant enhancement to the debugging experience, too.
switch (tree.kind) {
case ts.SyntaxKind.EmptyStatement:
// Additional semicolon where it doesn't belong.
return NO_SYNTAX;
case ts.SyntaxKind.SourceFile:
return visitor.sourceFile(tree as ts.SourceFile, this);
case ts.SyntaxKind.ImportEqualsDeclaration:
return visitor.importStatement(analyzeImportEquals(tree as ts.ImportEqualsDeclaration, this), this);
case ts.SyntaxKind.ImportDeclaration:
return new OTree(
[],
analyzeImportDeclaration(tree as ts.ImportDeclaration, this, this.submoduleReferences).map((import_) =>
visitor.importStatement(import_, this),
),
{ canBreakLine: true, separator: '\n' },
);
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
return visitor.stringLiteral(tree as ts.StringLiteral | ts.NoSubstitutionTemplateLiteral, this);
case ts.SyntaxKind.NumericLiteral:
return visitor.numericLiteral(tree as ts.NumericLiteral, this);
case ts.SyntaxKind.FunctionDeclaration:
return visitor.functionDeclaration(tree as ts.FunctionDeclaration, this);
case ts.SyntaxKind.Identifier:
return visitor.identifier(tree as ts.Identifier, this);
case ts.SyntaxKind.Block:
return visitor.block(tree as ts.Block, this);
case ts.SyntaxKind.Parameter:
return visitor.parameterDeclaration(tree as ts.ParameterDeclaration, this);
case ts.SyntaxKind.ReturnStatement:
return visitor.returnStatement(tree as ts.ReturnStatement, this);
case ts.SyntaxKind.BinaryExpression:
return visitor.binaryExpression(tree as ts.BinaryExpression, this);
case ts.SyntaxKind.IfStatement:
return visitor.ifStatement(tree as ts.IfStatement, this);
case ts.SyntaxKind.PropertyAccessExpression:
const submoduleReference = this.submoduleReferences?.get(tree as ts.PropertyAccessExpression);
return visitor.propertyAccessExpression(tree as ts.PropertyAccessExpression, this, submoduleReference);
case ts.SyntaxKind.AwaitExpression:
return visitor.awaitExpression(tree as ts.AwaitExpression, this);
case ts.SyntaxKind.CallExpression:
return visitor.callExpression(tree as ts.CallExpression, this);
case ts.SyntaxKind.ExpressionStatement:
return visitor.expressionStatement(tree as ts.ExpressionStatement, this);
case ts.SyntaxKind.ObjectLiteralExpression:
return visitor.objectLiteralExpression(tree as ts.ObjectLiteralExpression, this);
case ts.SyntaxKind.NewExpression:
return visitor.newExpression(tree as ts.NewExpression, this);
case ts.SyntaxKind.PropertyAssignment:
return visitor.propertyAssignment(tree as ts.PropertyAssignment, this);
case ts.SyntaxKind.VariableStatement:
return visitor.variableStatement(tree as ts.VariableStatement, this);
case ts.SyntaxKind.VariableDeclarationList:
return visitor.variableDeclarationList(tree as ts.VariableDeclarationList, this);
case ts.SyntaxKind.VariableDeclaration:
return visitor.variableDeclaration(tree as ts.VariableDeclaration, this);
case ts.SyntaxKind.ArrayLiteralExpression:
return visitor.arrayLiteralExpression(tree as ts.ArrayLiteralExpression, this);
case ts.SyntaxKind.ShorthandPropertyAssignment:
return visitor.shorthandPropertyAssignment(tree as ts.ShorthandPropertyAssignment, this);
case ts.SyntaxKind.ForOfStatement:
return visitor.forOfStatement(tree as ts.ForOfStatement, this);
case ts.SyntaxKind.ClassDeclaration:
return visitor.classDeclaration(tree as ts.ClassDeclaration, this);
case ts.SyntaxKind.Constructor:
return visitor.constructorDeclaration(tree as ts.ConstructorDeclaration, this);
case ts.SyntaxKind.PropertyDeclaration:
return visitor.propertyDeclaration(tree as ts.PropertyDeclaration, this);
case ts.SyntaxKind.ComputedPropertyName:
return visitor.computedPropertyName((tree as ts.ComputedPropertyName).expression, this);
case ts.SyntaxKind.MethodDeclaration:
return visitor.methodDeclaration(tree as ts.MethodDeclaration, this);
case ts.SyntaxKind.InterfaceDeclaration:
return visitor.interfaceDeclaration(tree as ts.InterfaceDeclaration, this);
case ts.SyntaxKind.PropertySignature:
return visitor.propertySignature(tree as ts.PropertySignature, this);
case ts.SyntaxKind.MethodSignature:
return visitor.methodSignature(tree as ts.MethodSignature, this);
case ts.SyntaxKind.AsExpression:
return visitor.asExpression(tree as ts.AsExpression, this);
case ts.SyntaxKind.PrefixUnaryExpression:
return visitor.prefixUnaryExpression(tree as ts.PrefixUnaryExpression, this);
case ts.SyntaxKind.SpreadAssignment:
if (this.textOf(tree) === '...') {
return visitor.ellipsis(tree as ts.SpreadAssignment, this);
}
return visitor.spreadAssignment(tree as ts.SpreadAssignment, this);
case ts.SyntaxKind.SpreadElement:
if (this.textOf(tree) === '...') {
return visitor.ellipsis(tree as ts.SpreadElement, this);
}
return visitor.spreadElement(tree as ts.SpreadElement, this);
case ts.SyntaxKind.ElementAccessExpression:
return visitor.elementAccessExpression(tree as ts.ElementAccessExpression, this);
case ts.SyntaxKind.TemplateExpression:
return visitor.templateExpression(tree as ts.TemplateExpression, this);
case ts.SyntaxKind.NonNullExpression:
return visitor.nonNullExpression(tree as ts.NonNullExpression, this);
case ts.SyntaxKind.ParenthesizedExpression:
return visitor.parenthesizedExpression(tree as ts.ParenthesizedExpression, this);
case ts.SyntaxKind.VoidExpression:
return visitor.maskingVoidExpression(tree as ts.VoidExpression, this);
case ts.SyntaxKind.JSDoc:
case ts.SyntaxKind.JSDocComment:
return visitor.jsDoc(tree as ts.JSDoc, this);
default:
if (ts.isToken(tree)) {
return visitor.token(tree, this);
}
this.reportUnsupported(tree, undefined);
}
if (this.options.bestEffort !== false) {
// When doing best-effort conversion and we don't understand the node type, just return the complete text of it as-is
return new OTree([this.textOf(tree)]);
}
// Otherwise, show a placeholder indicating we don't recognize the type
const nodeKind = ts.SyntaxKind[tree.kind];
return new UnknownSyntax(
[`<${nodeKind} ${this.textOf(tree)}>`],
['\n', ...nodeChildren(tree).map(this.convert.bind(this))],
{
indent: 2,
},
);
}