2018-02-16 18:57:51 +01:00
|
|
|
// Abstract Syntax Tree extras that are not needed in a standalone compiler but
|
|
|
|
// quite useful for testing the parser.
|
2018-02-16 11:55:13 +01:00
|
|
|
|
2018-01-15 19:00:18 +01:00
|
|
|
import {
|
|
|
|
Token,
|
|
|
|
|
|
|
|
Node,
|
|
|
|
NodeKind,
|
|
|
|
|
|
|
|
Source,
|
|
|
|
|
|
|
|
TypeNode,
|
|
|
|
TypeParameter,
|
|
|
|
|
|
|
|
Expression,
|
|
|
|
IdentifierExpression,
|
|
|
|
LiteralExpression,
|
|
|
|
LiteralKind,
|
|
|
|
FloatLiteralExpression,
|
|
|
|
IntegerLiteralExpression,
|
|
|
|
StringLiteralExpression,
|
|
|
|
RegexpLiteralExpression,
|
|
|
|
ArrayLiteralExpression,
|
|
|
|
AssertionExpression,
|
|
|
|
AssertionKind,
|
|
|
|
BinaryExpression,
|
|
|
|
CallExpression,
|
|
|
|
CommaExpression,
|
|
|
|
ElementAccessExpression,
|
|
|
|
NewExpression,
|
|
|
|
ParenthesizedExpression,
|
|
|
|
PropertyAccessExpression,
|
|
|
|
TernaryExpression,
|
|
|
|
UnaryPostfixExpression,
|
|
|
|
UnaryExpression,
|
|
|
|
UnaryPrefixExpression,
|
|
|
|
|
|
|
|
Statement,
|
|
|
|
BlockStatement,
|
|
|
|
BreakStatement,
|
|
|
|
ContinueStatement,
|
|
|
|
DoStatement,
|
|
|
|
EmptyStatement,
|
|
|
|
ExportImportStatement,
|
|
|
|
ExportStatement,
|
|
|
|
ExpressionStatement,
|
|
|
|
ForStatement,
|
|
|
|
IfStatement,
|
|
|
|
ImportStatement,
|
|
|
|
ReturnStatement,
|
|
|
|
SwitchStatement,
|
|
|
|
ThrowStatement,
|
|
|
|
TryStatement,
|
|
|
|
VariableStatement,
|
|
|
|
WhileStatement,
|
|
|
|
|
|
|
|
ClassDeclaration,
|
|
|
|
EnumDeclaration,
|
|
|
|
EnumValueDeclaration,
|
|
|
|
FieldDeclaration,
|
|
|
|
FunctionDeclaration,
|
|
|
|
ImportDeclaration,
|
|
|
|
InterfaceDeclaration,
|
|
|
|
MethodDeclaration,
|
|
|
|
NamespaceDeclaration,
|
|
|
|
TypeDeclaration,
|
|
|
|
VariableDeclaration,
|
|
|
|
|
|
|
|
Decorator,
|
|
|
|
Modifier,
|
|
|
|
ModifierKind,
|
|
|
|
Parameter,
|
2018-02-09 02:31:48 +01:00
|
|
|
ParameterKind,
|
2018-01-15 19:00:18 +01:00
|
|
|
ExportMember,
|
|
|
|
SwitchCase,
|
|
|
|
|
|
|
|
hasModifier
|
|
|
|
} from "../ast";
|
|
|
|
|
|
|
|
import {
|
|
|
|
CharCode
|
|
|
|
} from "../util/charcode";
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeNode(
|
|
|
|
node: Node,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
switch (node.kind) {
|
|
|
|
|
|
|
|
case NodeKind.SOURCE:
|
|
|
|
serializeSource(<Source>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// types
|
|
|
|
|
|
|
|
case NodeKind.TYPE:
|
|
|
|
serializeTypeNode(<TypeNode>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.TYPEPARAMETER:
|
|
|
|
serializeTypeParameter(<TypeParameter>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// expressions
|
|
|
|
|
|
|
|
case NodeKind.FALSE:
|
|
|
|
case NodeKind.NULL:
|
|
|
|
case NodeKind.SUPER:
|
|
|
|
case NodeKind.THIS:
|
|
|
|
case NodeKind.TRUE:
|
|
|
|
case NodeKind.CONSTRUCTOR:
|
|
|
|
case NodeKind.IDENTIFIER:
|
|
|
|
serializeIdentifierExpression(<IdentifierExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.ASSERTION:
|
|
|
|
serializeAssertionExpression(<AssertionExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.BINARY:
|
|
|
|
serializeBinaryExpression(<BinaryExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.CALL:
|
|
|
|
serializeCallExpression(<CallExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.ELEMENTACCESS:
|
|
|
|
serializeElementAccessExpression(<ElementAccessExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.LITERAL:
|
|
|
|
serializeLiteralExpression(<LiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.NEW:
|
|
|
|
serializeNewExpression(<NewExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.PARENTHESIZED:
|
|
|
|
serializeParenthesizedExpression(<ParenthesizedExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.PROPERTYACCESS:
|
|
|
|
serializePropertyAccessExpression(<PropertyAccessExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.TERNARY:
|
|
|
|
serializeTernaryExpression(<TernaryExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.UNARYPOSTFIX:
|
|
|
|
serializeUnaryPostfixExpression(<UnaryPostfixExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.UNARYPREFIX:
|
|
|
|
serializeUnaryPrefixExpression(<UnaryPrefixExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// statements
|
|
|
|
|
|
|
|
case NodeKind.BLOCK:
|
|
|
|
serializeBlockStatement(<BlockStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.BREAK:
|
|
|
|
serializeBreakStatement(<BreakStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.CONTINUE:
|
|
|
|
serializeContinueStatement(<ContinueStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.DO:
|
|
|
|
serializeDoStatement(<DoStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.EMPTY:
|
|
|
|
serializeEmptyStatement(<EmptyStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.EXPORT:
|
|
|
|
serializeExportStatement(<ExportStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.EXPORTIMPORT:
|
|
|
|
serializeExportImportStatement(<ExportImportStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.EXPRESSION:
|
|
|
|
serializeExpressionStatement(<ExpressionStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.FOR:
|
|
|
|
serializeForStatement(<ForStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.IF:
|
|
|
|
serializeIfStatement(<IfStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.IMPORT:
|
|
|
|
serializeImportStatement(<ImportStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.RETURN:
|
|
|
|
serializeReturnStatement(<ReturnStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.SWITCH:
|
|
|
|
serializeSwitchStatement(<SwitchStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.THROW:
|
|
|
|
serializeThrowStatement(<ThrowStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.TRY:
|
|
|
|
serializeTryStatement(<TryStatement>node, sb);
|
|
|
|
|
|
|
|
case NodeKind.VARIABLE:
|
|
|
|
serializeVariableStatement(<VariableStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.WHILE:
|
|
|
|
serializeWhileStatement(<WhileStatement>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// declaration statements
|
|
|
|
|
|
|
|
case NodeKind.CLASSDECLARATION:
|
|
|
|
serializeClassDeclaration(<ClassDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.ENUMDECLARATION:
|
|
|
|
serializeEnumDeclaration(<EnumDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.ENUMVALUEDECLARATION:
|
|
|
|
serializeEnumValueDeclaration(<EnumValueDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.FIELDDECLARATION:
|
|
|
|
serializeFieldDeclaration(<FieldDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.FUNCTIONDECLARATION:
|
|
|
|
serializeFunctionDeclaration(<FunctionDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.IMPORTDECLARATION:
|
|
|
|
serializeImportDeclaration(<ImportDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.INTERFACEDECLARATION:
|
|
|
|
serializeInterfaceDeclaration(<InterfaceDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.METHODDECLARATION:
|
|
|
|
serializeMethodDeclaration(<MethodDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.NAMESPACEDECLARATION:
|
|
|
|
serializeNamespaceDeclaration(<NamespaceDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.TYPEDECLARATION:
|
|
|
|
serializeTypeDeclaration(<TypeDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.VARIABLEDECLARATION:
|
|
|
|
serializeVariableDeclaration(<VariableDeclaration>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// other
|
|
|
|
|
|
|
|
case NodeKind.DECORATOR:
|
|
|
|
serializeDecorator(<Decorator>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.EXPORTMEMBER:
|
|
|
|
serializeExportMember(<ExportMember>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.MODIFIER:
|
|
|
|
serializeModifier(<Modifier>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.PARAMETER:
|
|
|
|
serializeParameter(<Parameter>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.SWITCHCASE:
|
|
|
|
serializeSwitchCase(<SwitchCase>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeSource(
|
|
|
|
source: Source,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
for (var i = 0, k = source.statements.length; i < k; ++i) {
|
|
|
|
serializeStatement(source.statements[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// types
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeTypeNode(
|
|
|
|
node: TypeNode,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(<IdentifierExpression>node.name, sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.typeArguments.length) {
|
|
|
|
sb.push("<");
|
|
|
|
for (var i = 0, k = node.typeArguments.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeNode(node.typeArguments[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (node.isNullable)
|
|
|
|
sb.push(" | null");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeTypeParameter(
|
|
|
|
node: TypeParameter,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.extendsType) {
|
|
|
|
sb.push(" extends ");
|
|
|
|
serializeTypeNode(node.extendsType, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// expressions
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeExpression(
|
|
|
|
node: Expression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeNode(node, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeIdentifierExpression(
|
|
|
|
node: IdentifierExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-14 19:21:31 +01:00
|
|
|
sb.push(node.text);
|
2018-01-15 19:00:18 +01:00
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeArrayLiteralExpression(
|
|
|
|
node: ArrayLiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("[");
|
|
|
|
for (var i = 0, k = node.elementExpressions.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
if (node.elementExpressions[i])
|
|
|
|
serializeExpression(<Expression>node.elementExpressions[i], sb);
|
|
|
|
}
|
|
|
|
sb.push("]");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeAssertionExpression(
|
|
|
|
node: AssertionExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.assertionKind == AssertionKind.PREFIX) {
|
|
|
|
sb.push("<");
|
|
|
|
serializeTypeNode(node.toType, sb);
|
|
|
|
sb.push(">");
|
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
} else {
|
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
sb.push(" as ");
|
|
|
|
serializeTypeNode(node.toType, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeBinaryExpression(
|
|
|
|
node: BinaryExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.left, sb);
|
|
|
|
sb.push(" ");
|
|
|
|
sb.push(operatorToString(node.operator));
|
|
|
|
sb.push(" ");
|
|
|
|
serializeExpression(node.right, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeCallExpression(
|
|
|
|
node: CallExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
var k: i32;
|
|
|
|
if (node.typeArguments && (k = node.typeArguments.length)) {
|
|
|
|
sb.push("<");
|
|
|
|
for (var i = 0; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeNode(node.typeArguments[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(">(");
|
|
|
|
} else
|
|
|
|
sb.push("(");
|
|
|
|
for (i = 0, k = node.arguments.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeExpression(node.arguments[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeCommaExpression(
|
|
|
|
node: CommaExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.expressions[0], sb);
|
|
|
|
for (var i = 1, k = node.expressions.length; i < k; ++i) {
|
|
|
|
sb.push(",");
|
|
|
|
serializeExpression(node.expressions[i], sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeElementAccessExpression(
|
|
|
|
node: ElementAccessExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
sb.push("[");
|
|
|
|
serializeExpression(node.elementExpression, sb);
|
|
|
|
sb.push("]");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeLiteralExpression(
|
|
|
|
node: LiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
switch (node.literalKind) {
|
|
|
|
|
|
|
|
case LiteralKind.FLOAT:
|
|
|
|
serializeFloatLiteralExpression(<FloatLiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LiteralKind.INTEGER:
|
|
|
|
serializeIntegerLiteralExpression(<IntegerLiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LiteralKind.STRING:
|
|
|
|
serializeStringLiteralExpression(<StringLiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LiteralKind.REGEXP:
|
|
|
|
serializeRegexpLiteralExpression(<RegexpLiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LiteralKind.ARRAY:
|
|
|
|
serializeArrayLiteralExpression(<ArrayLiteralExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// case LiteralKind.OBJECT:
|
|
|
|
// serializeObjectLiteralExpression(<ObjectLiteralExpression>node, sb);
|
|
|
|
// break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeFloatLiteralExpression(
|
|
|
|
node: FloatLiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(node.value.toString(10));
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeIntegerLiteralExpression(
|
|
|
|
node: IntegerLiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(node.value.toString());
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeStringLiteral(
|
|
|
|
str: string,
|
|
|
|
sb: string[],
|
|
|
|
singleQuoted: bool = false
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
var off = 0;
|
|
|
|
sb.push(singleQuoted ? "'" : "\"");
|
|
|
|
for (var i = 0, k = str.length; i < k;) {
|
|
|
|
switch (str.charCodeAt(i)) {
|
|
|
|
|
|
|
|
case CharCode.NULL:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, off = i + 1));
|
|
|
|
sb.push("\\0");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.BACKSPACE:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
sb.push("\\b");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.TAB:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
sb.push("\\t");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.LINEFEED:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
sb.push("\\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.VERTICALTAB:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
sb.push("\\v");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.FORMFEED:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
sb.push("\\f");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.CARRIAGERETURN:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
sb.push("\\r");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.DOUBLEQUOTE:
|
|
|
|
if (!singleQuoted) {
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
sb.push("\\\"");
|
|
|
|
off = ++i;
|
|
|
|
} else
|
|
|
|
++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.SINGLEQUOTE:
|
|
|
|
if (singleQuoted) {
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
sb.push("\\'");
|
|
|
|
off = ++i;
|
|
|
|
} else
|
|
|
|
++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.BACKSLASH:
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
sb.push("\\\\");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i > off)
|
|
|
|
sb.push(str.substring(off, i));
|
|
|
|
sb.push(singleQuoted ? "'" : "\"");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeStringLiteralExpression(
|
|
|
|
node: StringLiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeStringLiteral(node.value, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeRegexpLiteralExpression(
|
|
|
|
node: RegexpLiteralExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("/");
|
|
|
|
sb.push(node.pattern);
|
|
|
|
sb.push("/");
|
|
|
|
sb.push(node.patternFlags);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeNewExpression(
|
|
|
|
node: NewExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("new ");
|
|
|
|
serializeCallExpression(node, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeParenthesizedExpression(
|
|
|
|
node: ParenthesizedExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("(");
|
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializePropertyAccessExpression(
|
|
|
|
node: PropertyAccessExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
sb.push(".");
|
|
|
|
serializeIdentifierExpression(node.property, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeTernaryExpression(
|
|
|
|
node: TernaryExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
sb.push(" ? ");
|
|
|
|
serializeExpression(node.ifThen, sb);
|
|
|
|
sb.push(" : ");
|
|
|
|
serializeExpression(node.ifElse, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeUnaryExpression(
|
|
|
|
node: UnaryExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
switch (node.kind) {
|
|
|
|
|
|
|
|
case NodeKind.UNARYPOSTFIX:
|
|
|
|
serializeUnaryPostfixExpression(<UnaryPostfixExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NodeKind.UNARYPREFIX:
|
|
|
|
serializeUnaryPrefixExpression(<UnaryPrefixExpression>node, sb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeUnaryPostfixExpression(
|
|
|
|
node: UnaryPostfixExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.operand, sb);
|
|
|
|
sb.push(operatorToString(node.operator));
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeUnaryPrefixExpression(
|
|
|
|
node: UnaryPrefixExpression,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(operatorToString(node.operator));
|
|
|
|
serializeExpression(node.operand, sb);
|
|
|
|
}
|
|
|
|
|
|
|
|
// statements
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeStatement(
|
|
|
|
node: Statement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeNode(node, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeBlockStatement(
|
|
|
|
node: BlockStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("{\n");
|
|
|
|
for (var i = 0, k = node.statements.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.statements[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeBreakStatement(
|
|
|
|
node: BreakStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.label) {
|
|
|
|
sb.push("break ");
|
|
|
|
serializeIdentifierExpression(node.label, sb);
|
|
|
|
} else
|
|
|
|
sb.push("break");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeContinueStatement(
|
|
|
|
node: ContinueStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.label) {
|
|
|
|
sb.push("continue ");
|
|
|
|
serializeIdentifierExpression(node.label, sb);
|
|
|
|
} else
|
|
|
|
sb.push("continue");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeClassDeclaration(
|
|
|
|
node: ClassDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("class ");
|
2018-02-14 19:21:31 +01:00
|
|
|
sb.push(node.name.text);
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.typeParameters.length) {
|
|
|
|
sb.push("<");
|
|
|
|
for (i = 0, k = node.typeParameters.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeParameter(node.typeParameters[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (node.extendsType) {
|
|
|
|
sb.push(" extends ");
|
|
|
|
serializeTypeNode(node.extendsType, sb);
|
|
|
|
}
|
|
|
|
if (node.implementsTypes.length) {
|
|
|
|
sb.push(" implements ");
|
|
|
|
for (i = 0, k = node.implementsTypes.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeNode(node.implementsTypes[i], sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sb.push(" {\n");
|
|
|
|
for (i = 0, k = node.members.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.members[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeDoStatement(
|
|
|
|
node: DoStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("do ");
|
|
|
|
serializeStatement(node.statement, sb);
|
|
|
|
if (node.statement.kind == NodeKind.BLOCK)
|
|
|
|
sb.push(" while (");
|
|
|
|
else
|
|
|
|
sb.push(";\nwhile (");
|
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeEmptyStatement(
|
|
|
|
node: EmptyStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {}
|
2018-01-15 19:00:18 +01:00
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeEnumDeclaration(
|
|
|
|
node: EnumDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.modifiers)
|
|
|
|
for (var i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("enum ");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
sb.push(" {\n");
|
|
|
|
for (i = 0, k = node.values.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
|
|
|
serializeEnumValueDeclaration(node.values[i], sb);
|
|
|
|
}
|
|
|
|
sb.push("\n}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeEnumValueDeclaration(
|
|
|
|
node: EnumValueDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.value) {
|
|
|
|
sb.push(" = ");
|
|
|
|
serializeExpression(node.value, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeExportImportStatement(
|
|
|
|
node: ExportImportStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("export import ");
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.externalName, sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(" = ");
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeExportMember(
|
|
|
|
node: ExportMember,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.externalName.text != node.name.text) {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(" as ");
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.externalName, sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeExportStatement(
|
|
|
|
node: ExportStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.modifiers)
|
|
|
|
for (var i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("export {\n");
|
|
|
|
for (i = 0, k = node.members.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
|
|
|
serializeExportMember(node.members[i], sb);
|
|
|
|
}
|
|
|
|
if (node.path) {
|
|
|
|
sb.push("\n} from ");
|
|
|
|
serializeStringLiteralExpression(node.path, sb);
|
|
|
|
} else
|
|
|
|
sb.push("\n}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeExpressionStatement(
|
|
|
|
node: ExpressionStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeExpression(node.expression, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeFieldDeclaration(
|
|
|
|
node: FieldDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.type) {
|
|
|
|
sb.push(": ");
|
|
|
|
serializeTypeNode(node.type, sb);
|
|
|
|
}
|
|
|
|
if (node.initializer) {
|
|
|
|
sb.push(" = ");
|
|
|
|
serializeExpression(node.initializer, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeForStatement(
|
|
|
|
node: ForStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("for (");
|
|
|
|
if (node.initializer)
|
|
|
|
serializeStatement(node.initializer, sb);
|
|
|
|
if (node.condition) {
|
|
|
|
sb.push("; ");
|
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
} else
|
|
|
|
sb.push(";");
|
|
|
|
if (node.incrementor) {
|
|
|
|
sb.push("; ");
|
|
|
|
serializeExpression(node.incrementor, sb);
|
|
|
|
} else
|
|
|
|
sb.push(";");
|
|
|
|
sb.push(") ");
|
|
|
|
serializeStatement(node.statement, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeFunctionDeclaration(
|
|
|
|
node: FunctionDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("function ");
|
|
|
|
serializeFunctionCommon(node, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
function serializeFunctionCommon(
|
|
|
|
node: FunctionDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.typeParameters.length) {
|
|
|
|
sb.push("<");
|
|
|
|
for (var i = 0, k = node.typeParameters.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeParameter(node.typeParameters[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
sb.push("(");
|
|
|
|
for (i = 0, k = node.parameters.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeParameter(node.parameters[i], sb);
|
|
|
|
}
|
|
|
|
if (node.returnType && !hasModifier(ModifierKind.SET, node.modifiers)) {
|
|
|
|
sb.push("): ");
|
|
|
|
serializeTypeNode(node.returnType, sb);
|
|
|
|
} else
|
|
|
|
sb.push(")");
|
|
|
|
if (node.statements) {
|
|
|
|
sb.push(" {\n");
|
|
|
|
for (i = 0, k = node.statements.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.statements[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeIfStatement(
|
|
|
|
node: IfStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("if (");
|
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
sb.push(") ");
|
|
|
|
serializeStatement(node.ifTrue, sb);
|
|
|
|
if (node.ifTrue.kind != NodeKind.BLOCK)
|
|
|
|
sb.push(";\n");
|
|
|
|
if (node.ifFalse) {
|
|
|
|
if (node.ifTrue.kind == NodeKind.BLOCK)
|
|
|
|
sb.push(" else ");
|
|
|
|
else
|
|
|
|
sb.push("else ");
|
|
|
|
serializeStatement(node.ifFalse, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeImportDeclaration(
|
|
|
|
node: ImportDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-14 19:21:31 +01:00
|
|
|
serializeIdentifierExpression(node.externalName, sb);
|
|
|
|
if (node.externalName.text != node.name.text) {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(" as ");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeImportStatement(
|
|
|
|
node: ImportStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("import ");
|
|
|
|
if (node.declarations) {
|
|
|
|
sb.push("{\n");
|
|
|
|
for (var i: i32 = 0, k: i32 = node.declarations.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
|
|
|
serializeImportDeclaration(node.declarations[i], sb);
|
|
|
|
}
|
|
|
|
sb.push("\n} from ");
|
|
|
|
} else if (node.namespaceName) {
|
|
|
|
sb.push("* as ");
|
|
|
|
serializeIdentifierExpression(node.namespaceName, sb);
|
|
|
|
sb.push(" from ");
|
|
|
|
}
|
|
|
|
serializeStringLiteralExpression(node.path, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeInterfaceDeclaration(
|
|
|
|
node: InterfaceDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("interface ");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.typeParameters.length) {
|
|
|
|
sb.push("<");
|
|
|
|
for (i = 0, k = node.typeParameters.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeTypeParameter(node.typeParameters[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (node.extendsType) {
|
|
|
|
sb.push(" extends ");
|
|
|
|
serializeTypeNode(node.extendsType, sb);
|
|
|
|
}
|
|
|
|
sb.push(" {\n");
|
|
|
|
for (i = 0, k = node.members.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.members[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeMethodDeclaration(
|
|
|
|
node: MethodDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
serializeFunctionCommon(node, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeNamespaceDeclaration(
|
|
|
|
node: NamespaceDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("namespace ");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
sb.push(" {\n");
|
|
|
|
for (i = 0, k = node.members.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.members[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeReturnStatement(
|
|
|
|
node: ReturnStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.value) {
|
|
|
|
sb.push("return ");
|
|
|
|
serializeExpression(node.value, sb);
|
|
|
|
} else
|
|
|
|
sb.push("return");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeSwitchCase(
|
|
|
|
node: SwitchCase,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.label) {
|
|
|
|
sb.push("case ");
|
|
|
|
serializeExpression(node.label, sb);
|
|
|
|
sb.push(":\n");
|
|
|
|
} else
|
|
|
|
sb.push("default:\n");
|
|
|
|
for (var i = 0, k = node.statements.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push("\n");
|
|
|
|
serializeStatement(node.statements[i], sb);
|
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeSwitchStatement(
|
|
|
|
node: SwitchStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("switch (");
|
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
sb.push(") {\n");
|
|
|
|
for (var i = 0, k = node.cases.length; i < k; ++i) {
|
|
|
|
serializeSwitchCase(node.cases[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeThrowStatement(
|
|
|
|
node: ThrowStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("throw ");
|
|
|
|
serializeExpression(node.value, sb);
|
|
|
|
sb.push(";");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeTryStatement(
|
|
|
|
node: TryStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("try {\n");
|
|
|
|
for (var i = 0, k = node.statements.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.statements[i], sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
if (node.catchVariable) {
|
|
|
|
sb.push("} catch (");
|
|
|
|
serializeIdentifierExpression(node.catchVariable, sb);
|
|
|
|
sb.push(") {\n");
|
|
|
|
if (node.catchStatements)
|
|
|
|
for (i = 0, k = node.catchStatements.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.catchStatements[i], sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (node.finallyStatements) {
|
|
|
|
sb.push("} finally {\n");
|
|
|
|
for (i = 0, k = node.finallyStatements.length; i < k; ++i) {
|
|
|
|
serializeStatement(node.finallyStatements[i], sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeTypeDeclaration(
|
|
|
|
node: TypeDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
|
|
|
serializeModifier(node.modifiers[i], sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("type ");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
sb.push(" = ");
|
|
|
|
serializeTypeNode(node.alias, sb);
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeVariableDeclaration(
|
|
|
|
node: VariableDeclaration,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.type) {
|
|
|
|
sb.push(": ");
|
|
|
|
serializeTypeNode(node.type, sb);
|
|
|
|
}
|
|
|
|
if (node.initializer) {
|
|
|
|
sb.push(" = ");
|
|
|
|
serializeExpression(node.initializer, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeVariableStatement(
|
|
|
|
node: VariableStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.decorators)
|
|
|
|
for (var i = 0, k = node.decorators.length; i < k; ++i) {
|
|
|
|
serializeDecorator(node.decorators[i], sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2018-02-16 11:55:13 +01:00
|
|
|
var isConst = false, isLet = false;
|
2018-01-15 19:00:18 +01:00
|
|
|
if (node.modifiers)
|
|
|
|
for (i = 0, k = node.modifiers.length; i < k; ++i) {
|
2018-02-16 11:55:13 +01:00
|
|
|
var modifier = node.modifiers[i];
|
|
|
|
switch (modifier.modifierKind) {
|
|
|
|
|
|
|
|
case ModifierKind.CONST:
|
|
|
|
assert(!isLet);
|
|
|
|
isConst = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ModifierKind.LET:
|
|
|
|
assert(!isConst);
|
|
|
|
isLet = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
serializeModifier(modifier, sb);
|
|
|
|
sb.push(" ");
|
|
|
|
break;
|
|
|
|
}
|
2018-01-15 19:00:18 +01:00
|
|
|
}
|
2018-02-16 11:55:13 +01:00
|
|
|
sb.push(isConst ? "const " : isLet ? "let " : "var ");
|
2018-01-15 19:00:18 +01:00
|
|
|
for (i = 0, k = node.declarations.length; i < k; ++i) {
|
2018-02-16 11:55:13 +01:00
|
|
|
if (i) sb.push(", ");
|
|
|
|
serializeVariableDeclaration(node.declarations[i], sb);
|
2018-01-15 19:00:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeWhileStatement(
|
|
|
|
node: WhileStatement,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("while (");
|
|
|
|
serializeExpression(node.condition, sb);
|
|
|
|
sb.push(") ");
|
|
|
|
serializeStatement(node.statement, sb);
|
|
|
|
}
|
|
|
|
|
|
|
|
// other
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeDecorator(
|
|
|
|
node: Decorator,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("@");
|
|
|
|
serializeExpression(node.name, sb);
|
|
|
|
if (node.arguments) {
|
|
|
|
sb.push("(");
|
|
|
|
for (var i = 0, k = node.arguments.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
serializeExpression(node.arguments[i], sb);
|
|
|
|
}
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeModifier(
|
|
|
|
node: Modifier,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push(modifierToString(node));
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function serializeParameter(
|
|
|
|
node: Parameter,
|
|
|
|
sb: string[]
|
|
|
|
): void {
|
2018-02-09 02:31:48 +01:00
|
|
|
if (node.parameterKind == ParameterKind.REST)
|
2018-01-15 19:00:18 +01:00
|
|
|
sb.push("...");
|
|
|
|
serializeIdentifierExpression(node.name, sb);
|
|
|
|
if (node.type) {
|
2018-02-09 02:31:48 +01:00
|
|
|
if (node.parameterKind == ParameterKind.OPTIONAL && !node.initializer)
|
|
|
|
sb.push("?: ");
|
|
|
|
else
|
|
|
|
sb.push(": ");
|
2018-01-15 19:00:18 +01:00
|
|
|
serializeTypeNode(node.type, sb);
|
|
|
|
}
|
|
|
|
if (node.initializer) {
|
|
|
|
sb.push(" = ");
|
|
|
|
serializeExpression(node.initializer, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// helpers
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
export function operatorToString(
|
|
|
|
token: Token
|
|
|
|
): string {
|
|
|
|
switch (token) {
|
|
|
|
case Token.DELETE: return "delete";
|
|
|
|
case Token.IN: return "in";
|
|
|
|
case Token.INSTANCEOF: return "instanceof";
|
|
|
|
case Token.NEW: return "new";
|
|
|
|
case Token.TYPEOF: return "typeof";
|
|
|
|
case Token.VOID: return "void";
|
|
|
|
case Token.YIELD: return "yield";
|
|
|
|
case Token.DOT_DOT_DOT: return "...";
|
|
|
|
case Token.COMMA: return ",";
|
|
|
|
case Token.LESSTHAN: return "<";
|
|
|
|
case Token.GREATERTHAN: return ">";
|
|
|
|
case Token.LESSTHAN_EQUALS: return "<=";
|
|
|
|
case Token.GREATERTHAN_EQUALS: return ">=";
|
|
|
|
case Token.EQUALS_EQUALS: return "==";
|
|
|
|
case Token.EXCLAMATION_EQUALS: return "!=";
|
|
|
|
case Token.EQUALS_EQUALS_EQUALS: return "===";
|
|
|
|
case Token.EXCLAMATION_EQUALS_EQUALS: return "!==";
|
|
|
|
case Token.PLUS: return "+";
|
|
|
|
case Token.MINUS: return "-";
|
|
|
|
case Token.ASTERISK_ASTERISK: return "**";
|
|
|
|
case Token.ASTERISK: return "*";
|
|
|
|
case Token.SLASH: return "/";
|
|
|
|
case Token.PERCENT: return "%";
|
|
|
|
case Token.PLUS_PLUS: return "++";
|
|
|
|
case Token.MINUS_MINUS: return "--";
|
|
|
|
case Token.LESSTHAN_LESSTHAN: return "<<";
|
|
|
|
case Token.GREATERTHAN_GREATERTHAN: return ">>";
|
|
|
|
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>";
|
|
|
|
case Token.AMPERSAND: return "&";
|
|
|
|
case Token.BAR: return "|";
|
|
|
|
case Token.CARET: return "^";
|
|
|
|
case Token.EXCLAMATION: return "!";
|
|
|
|
case Token.TILDE: return "~";
|
|
|
|
case Token.AMPERSAND_AMPERSAND: return "&&";
|
|
|
|
case Token.BAR_BAR: return "||";
|
|
|
|
case Token.EQUALS: return "=";
|
|
|
|
case Token.PLUS_EQUALS: return "+=";
|
|
|
|
case Token.MINUS_EQUALS: return "-=";
|
|
|
|
case Token.ASTERISK_EQUALS: return "*=";
|
|
|
|
case Token.ASTERISK_ASTERISK_EQUALS: return "**=";
|
|
|
|
case Token.SLASH_EQUALS: return "/=";
|
|
|
|
case Token.PERCENT_EQUALS: return "%=";
|
|
|
|
case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<=";
|
|
|
|
case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>=";
|
|
|
|
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>=";
|
|
|
|
case Token.AMPERSAND_EQUALS: return "&=";
|
|
|
|
case Token.BAR_EQUALS: return "|=";
|
|
|
|
case Token.CARET_EQUALS: return "^=";
|
|
|
|
default: assert(false); return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function modifierToString(
|
|
|
|
node: Modifier
|
|
|
|
): string {
|
|
|
|
switch (node.modifierKind) {
|
|
|
|
case ModifierKind.ASYNC: return "async";
|
|
|
|
case ModifierKind.CONST: return "const";
|
|
|
|
case ModifierKind.LET: return "let"; // unused
|
|
|
|
case ModifierKind.DECLARE: return "declare";
|
|
|
|
case ModifierKind.EXPORT: return "export";
|
|
|
|
case ModifierKind.IMPORT: return "import";
|
|
|
|
case ModifierKind.STATIC: return "static";
|
|
|
|
case ModifierKind.ABSTRACT: return "abstract";
|
|
|
|
case ModifierKind.PUBLIC: return "public";
|
|
|
|
case ModifierKind.PRIVATE: return "private";
|
|
|
|
case ModifierKind.PROTECTED: return "protected";
|
|
|
|
case ModifierKind.READONLY: return "readonly";
|
|
|
|
case ModifierKind.GET: return "get";
|
|
|
|
case ModifierKind.SET: return "set";
|
|
|
|
default: assert(false); return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function builderEndsWith(
|
|
|
|
sb: string[],
|
|
|
|
code: CharCode
|
|
|
|
): bool {
|
2018-01-15 19:00:18 +01:00
|
|
|
if (sb.length) {
|
|
|
|
var last = sb[sb.length - 1];
|
|
|
|
return last.length > 0 ? last.charCodeAt(last.length - 1) == code : false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|