2017-12-24 03:19:47 +01:00
|
|
|
import {
|
|
|
|
PATH_DELIMITER,
|
|
|
|
STATIC_DELIMITER,
|
|
|
|
INSTANCE_DELIMITER
|
|
|
|
} from "./constants";
|
|
|
|
|
|
|
|
import {
|
|
|
|
Token,
|
|
|
|
Tokenizer,
|
|
|
|
Range
|
|
|
|
} from "./tokenizer";
|
|
|
|
|
2018-01-02 05:02:05 +01:00
|
|
|
import {
|
2017-12-24 03:19:47 +01:00
|
|
|
CharCode
|
|
|
|
} from "./util/charcode";
|
|
|
|
|
|
|
|
import {
|
|
|
|
I64
|
|
|
|
} from "./util/i64";
|
|
|
|
|
|
|
|
import {
|
|
|
|
normalize as normalizePath,
|
|
|
|
resolve as resolvePath
|
|
|
|
} from "./util/path";
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
export { Range } from "./tokenizer";
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Indicates the kind of a node. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export enum NodeKind {
|
|
|
|
|
|
|
|
SOURCE,
|
|
|
|
|
|
|
|
// types
|
|
|
|
TYPE,
|
|
|
|
TYPEPARAMETER,
|
|
|
|
|
|
|
|
// expressions
|
|
|
|
IDENTIFIER,
|
|
|
|
ASSERTION,
|
|
|
|
BINARY,
|
|
|
|
CALL,
|
2018-01-05 01:55:59 +01:00
|
|
|
COMMA,
|
2017-09-28 13:08:25 +02:00
|
|
|
ELEMENTACCESS,
|
2017-10-07 14:29:43 +02:00
|
|
|
FALSE,
|
2017-09-28 13:08:25 +02:00
|
|
|
LITERAL,
|
|
|
|
NEW,
|
2017-10-07 14:29:43 +02:00
|
|
|
NULL,
|
2017-09-28 13:08:25 +02:00
|
|
|
PARENTHESIZED,
|
|
|
|
PROPERTYACCESS,
|
2017-12-04 14:49:24 +01:00
|
|
|
TERNARY,
|
2017-10-07 14:29:43 +02:00
|
|
|
SUPER,
|
|
|
|
THIS,
|
|
|
|
TRUE,
|
2017-12-16 02:27:39 +01:00
|
|
|
CONSTRUCTOR,
|
2017-09-28 13:08:25 +02:00
|
|
|
UNARYPOSTFIX,
|
|
|
|
UNARYPREFIX,
|
|
|
|
|
|
|
|
// statements
|
|
|
|
BLOCK,
|
|
|
|
BREAK,
|
2017-12-18 03:46:36 +01:00
|
|
|
CASE,
|
2017-09-28 13:08:25 +02:00
|
|
|
CLASS, // is also declaration
|
|
|
|
CONTINUE,
|
|
|
|
DO,
|
|
|
|
EMPTY,
|
|
|
|
ENUM, // is also declaration
|
|
|
|
ENUMVALUE, // is also declaration
|
|
|
|
EXPORT,
|
|
|
|
EXPORTIMPORT,
|
2017-09-29 17:25:02 +02:00
|
|
|
EXPORTMEMBER,
|
2017-09-28 13:08:25 +02:00
|
|
|
EXPRESSION,
|
|
|
|
INTERFACE,
|
|
|
|
FOR,
|
|
|
|
FUNCTION, // is also declaration
|
|
|
|
IF,
|
|
|
|
IMPORT, // wraps declarations
|
|
|
|
IMPORTDECLARATION,
|
|
|
|
METHOD, // is also declaration
|
|
|
|
NAMESPACE, // is also declaration
|
|
|
|
FIELD,
|
|
|
|
RETURN,
|
|
|
|
SWITCH,
|
|
|
|
THROW,
|
|
|
|
TRY,
|
2017-12-19 17:49:15 +01:00
|
|
|
TYPEDECLARATION,
|
2017-09-28 13:08:25 +02:00
|
|
|
VARIABLE, // wraps declarations
|
|
|
|
VARIABLEDECLARATION,
|
2017-12-18 03:46:36 +01:00
|
|
|
WHILE,
|
|
|
|
|
|
|
|
// other
|
|
|
|
DECORATOR,
|
|
|
|
MODIFIER,
|
|
|
|
PARAMETER
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Base class of all nodes. */
|
|
|
|
export abstract class Node {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Node kind indicator. */
|
|
|
|
kind: NodeKind;
|
|
|
|
/** Source range. */
|
|
|
|
range: Range;
|
|
|
|
/** Parent node. */
|
|
|
|
parent: Node | null = null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Serializes this node to its TypeScript representation. Note that formatting is lost and long integers become hex literals. */
|
|
|
|
abstract serialize(sb: string[]): void;
|
|
|
|
|
|
|
|
// types
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
static createType(identifier: IdentifierExpression, typeArguments: TypeNode[], isNullable: bool, range: Range): TypeNode {
|
2017-12-28 04:09:40 +01:00
|
|
|
var type = new TypeNode();
|
2017-09-28 13:08:25 +02:00
|
|
|
type.range = range;
|
|
|
|
type.identifier = identifier;
|
2017-12-16 17:54:53 +01:00
|
|
|
type.typeArguments = typeArguments;
|
|
|
|
type.isNullable = isNullable;
|
2017-09-28 13:08:25 +02:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
// expressions
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createIdentifierExpression(name: string, range: Range): IdentifierExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new IdentifierExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.name = name;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createArrayLiteralExpression(elementExpressions: (Expression | null)[], range: Range): ArrayLiteralExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new ArrayLiteralExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (expr.elementExpressions = elementExpressions).length; i < k; ++i)
|
|
|
|
if (elementExpressions[i])
|
|
|
|
(<Expression>elementExpressions[i]).parent = expr;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createAssertionExpression(assertionKind: AssertionKind, expression: Expression, toType: TypeNode, range: Range): AssertionExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new AssertionExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.assertionKind = assertionKind;
|
|
|
|
(expr.expression = expression).parent = expr;
|
|
|
|
(expr.toType = toType).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createBinaryExpression(operator: Token, left: Expression, right: Expression, range: Range): BinaryExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new BinaryExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.operator = operator;
|
|
|
|
(expr.left = left).parent = expr;
|
|
|
|
(expr.right = right).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createCallExpression(expression: Expression, typeArguments: TypeNode[] | null, args: Expression[], range: Range): CallExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new CallExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.expression = expression).parent = expr;
|
2018-01-01 20:27:21 +01:00
|
|
|
if (expr.typeArguments = typeArguments)
|
|
|
|
for (var i = 0, k = (<TypeNode[]>typeArguments).length; i < k; ++i)
|
|
|
|
(<TypeNode[]>typeArguments)[i].parent = expr;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
|
|
|
args[i].parent = expr;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createCommaExpression(expressions: Expression[], range: Range): CommaExpression {
|
|
|
|
var expr = new CommaExpression();
|
|
|
|
expr.range = range;
|
|
|
|
for (var i = 0, k = (expr.expressions = expressions).length; i < k; ++i)
|
|
|
|
expressions[i].parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static createConstructorExpression(range: Range): ConstructorExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new ConstructorExpression();
|
2017-12-16 02:27:39 +01:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createElementAccessExpression(expression: Expression, element: Expression, range: Range): ElementAccessExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new ElementAccessExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.expression = expression).parent = expr;
|
|
|
|
(expr.elementExpression = element).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createFalseExpression(range: Range): FalseExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new FalseExpression();
|
2017-10-07 14:29:43 +02:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createFloatLiteralExpression(value: f64, range: Range): FloatLiteralExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new FloatLiteralExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.value = value;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createIntegerLiteralExpression(value: I64, range: Range): IntegerLiteralExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new IntegerLiteralExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.value = value;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createNewExpression(expression: Expression, typeArguments: TypeNode[] | null, args: Expression[], range: Range): NewExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new NewExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.expression = expression).parent = expr;
|
2018-01-01 20:27:21 +01:00
|
|
|
if (expr.typeArguments = typeArguments)
|
|
|
|
for (var i = 0, k = (<TypeNode[]>typeArguments).length; i < k; ++i)
|
|
|
|
(<TypeNode[]>typeArguments)[i].parent = expr;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
|
|
|
args[i].parent = expr;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createNullExpression(range: Range): NullExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new NullExpression();
|
2017-10-07 14:29:43 +02:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createParenthesizedExpression(expression: Expression, range: Range): ParenthesizedExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new ParenthesizedExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.expression = expression).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createPropertyAccessExpression(expression: Expression, property: IdentifierExpression, range: Range): PropertyAccessExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new PropertyAccessExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.expression = expression).parent = expr;
|
|
|
|
(expr.property = property).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-07 15:07:46 +01:00
|
|
|
static createRegexpLiteralExpression(pattern: string, modifiers: string, range: Range): RegexpLiteralExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new RegexpLiteralExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
2018-01-07 15:07:46 +01:00
|
|
|
expr.pattern = pattern;
|
|
|
|
expr.modifiers = modifiers;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createTernaryExpression(condition: Expression, ifThen: Expression, ifElse: Expression, range: Range): TernaryExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new TernaryExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
(expr.condition = condition).parent = expr;
|
|
|
|
(expr.ifThen = ifThen).parent = expr;
|
|
|
|
(expr.ifElse = ifElse).parent = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createStringLiteralExpression(value: string, range: Range): StringLiteralExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new StringLiteralExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.value = value;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createSuperExpression(range: Range): SuperExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new SuperExpression();
|
2017-10-07 14:29:43 +02:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createThisExpression(range: Range): ThisExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new ThisExpression();
|
2017-10-07 14:29:43 +02:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createTrueExpression(range: Range): TrueExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new TrueExpression();
|
2017-10-07 14:29:43 +02:00
|
|
|
expr.range = range;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createUnaryPostfixExpression(operator: Token, expression: Expression, range: Range): UnaryPostfixExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new UnaryPostfixExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.operator = operator;
|
2017-12-18 03:46:36 +01:00
|
|
|
(expr.operand = expression).parent = expr;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createUnaryPrefixExpression(operator: Token, expression: Expression, range: Range): UnaryPrefixExpression {
|
2017-12-28 04:09:40 +01:00
|
|
|
var expr = new UnaryPrefixExpression();
|
2017-09-28 13:08:25 +02:00
|
|
|
expr.range = range;
|
|
|
|
expr.operator = operator;
|
2017-12-18 03:46:36 +01:00
|
|
|
(expr.operand = expression).parent = expr;
|
2017-09-28 13:08:25 +02:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
// statements
|
2017-12-16 02:27:39 +01:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createBlockStatement(statements: Statement[], range: Range): BlockStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new BlockStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i: i32 = 0, k: i32 = (stmt.statements = statements).length; i < k; ++i)
|
|
|
|
statements[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
2017-12-16 02:27:39 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createBreakStatement(label: IdentifierExpression | null, range: Range): BreakStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new BreakStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.label = label)
|
|
|
|
(<IdentifierExpression>label).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createClassDeclaration(identifier: IdentifierExpression, typeParameters: TypeParameter[], extendsType: TypeNode | null, implementsTypes: TypeNode[], members: DeclarationStatement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): ClassDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ClassDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i)
|
|
|
|
typeParameters[i].parent = stmt;
|
|
|
|
if (stmt.extendsType = extendsType)
|
|
|
|
(<TypeNode>extendsType).parent = stmt;
|
|
|
|
for (i = 0, k = (stmt.implementsTypes = implementsTypes).length; i < k; ++i)
|
|
|
|
implementsTypes[i].parent = stmt;
|
|
|
|
for (i = 0, k = (stmt.members = members).length; i < k; ++i)
|
|
|
|
members[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createContinueStatement(label: IdentifierExpression | null, range: Range): ContinueStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ContinueStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.label = label)
|
|
|
|
(<IdentifierExpression>label).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-01 20:27:21 +01:00
|
|
|
static createDecorator(expression: Expression, args: Expression[] | null, range: Range): Decorator {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new Decorator();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = expression).parent = stmt;
|
2018-01-01 20:27:21 +01:00
|
|
|
if (stmt.arguments = args)
|
|
|
|
for (var i: i32 = 0, k: i32 = (<Expression[]>args).length; i < k; ++i)
|
|
|
|
(<Expression[]>args)[i].parent = stmt;
|
2018-01-06 10:20:38 +01:00
|
|
|
if (expression.kind == NodeKind.IDENTIFIER) {
|
|
|
|
switch ((<IdentifierExpression>expression).name) {
|
|
|
|
|
|
|
|
case "global":
|
|
|
|
stmt.decoratorKind = DecoratorKind.GLOBAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "operator":
|
|
|
|
stmt.decoratorKind = DecoratorKind.OPERATOR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "struct":
|
|
|
|
stmt.decoratorKind = DecoratorKind.STRUCT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "size":
|
|
|
|
stmt.decoratorKind = DecoratorKind.SIZE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
stmt.decoratorKind = DecoratorKind.CUSTOM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
stmt.decoratorKind = DecoratorKind.CUSTOM;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createDoStatement(statement: Statement, condition: Expression, range: Range): DoStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new DoStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
|
|
|
(stmt.statement = statement).parent = stmt;
|
|
|
|
(stmt.condition = condition).parent = stmt;
|
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createEmptyStatement(range: Range): EmptyStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new EmptyStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createEnumDeclaration(identifier: IdentifierExpression, members: EnumValueDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): EnumDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new EnumDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.values = members).length; i < k; ++i)
|
|
|
|
members[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createEnumValueDeclaration(identifier: IdentifierExpression, value: Expression | null, range: Range): EnumValueDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new EnumValueDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.value = value)
|
|
|
|
(<Expression>value).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createExportStatement(members: ExportMember[], path: StringLiteralExpression | null, modifiers: Modifier[] | null, range: Range): ExportStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ExportStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.path = path;
|
|
|
|
stmt.normalizedPath = path ? resolvePath(normalizePath(path.value), range.source.normalizedPath) : null;
|
|
|
|
stmt.internalPath = stmt.normalizedPath ? mangleInternalPath(stmt.normalizedPath) : null;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createExportImportStatement(identifier: IdentifierExpression, asIdentifier: IdentifierExpression, range: Range): ExportImportStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ExportImportStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
|
|
|
(stmt.identifier = identifier).parent = stmt;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.externalIdentifier = asIdentifier).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
static createExportMember(identifier: IdentifierExpression, externalIdentifier: IdentifierExpression | null, range: Range): ExportMember {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new ExportMember();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
|
|
|
(elem.identifier = identifier).parent = elem;
|
|
|
|
(elem.externalIdentifier = externalIdentifier ? <IdentifierExpression>externalIdentifier : identifier).parent = elem;
|
|
|
|
return elem;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
/** Creates an expression statement. */
|
2018-01-05 01:55:59 +01:00
|
|
|
static createExpressionStatement(expression: Expression): ExpressionStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ExpressionStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = expression.range;
|
|
|
|
(stmt.expression = expression).parent = stmt;
|
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createIfStatement(condition: Expression, ifTrue: Statement, ifFalse: Statement | null, range: Range): IfStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new IfStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
|
|
|
(stmt.condition = condition).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
(stmt.ifTrue = ifTrue).parent = stmt;
|
|
|
|
if (stmt.ifFalse = ifFalse)
|
|
|
|
(<Statement>ifFalse).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2018-01-05 18:19:32 +01:00
|
|
|
static createImportStatement(declarations: ImportDeclaration[] | null, path: StringLiteralExpression, range: Range): ImportStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ImportStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2018-01-05 18:19:32 +01:00
|
|
|
if (stmt.declarations = declarations)
|
|
|
|
for (var i: i32 = 0, k: i32 = (<ImportDeclaration[]>declarations).length; i < k; ++i)
|
|
|
|
(<ImportDeclaration[]>declarations)[i].parent = stmt;
|
2017-12-23 00:48:54 +01:00
|
|
|
stmt.namespaceName = null;
|
|
|
|
stmt.path = path;
|
|
|
|
stmt.normalizedPath = resolvePath(normalizePath(path.value), range.source.normalizedPath);
|
|
|
|
stmt.internalPath = mangleInternalPath(stmt.normalizedPath);
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createImportStatementWithWildcard(identifier: IdentifierExpression, path: StringLiteralExpression, range: Range): ImportStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ImportStatement();
|
2017-12-23 00:48:54 +01:00
|
|
|
stmt.range = range;
|
|
|
|
stmt.declarations = null;
|
|
|
|
stmt.namespaceName = identifier;
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.path = path;
|
|
|
|
stmt.normalizedPath = resolvePath(normalizePath(path.value), range.source.normalizedPath);
|
|
|
|
stmt.internalPath = mangleInternalPath(stmt.normalizedPath);
|
|
|
|
return stmt;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
static createImportDeclaration(externalIdentifier: IdentifierExpression, identifier: IdentifierExpression | null, range: Range): ImportDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new ImportDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(elem.name = identifier ? <IdentifierExpression>identifier : externalIdentifier).parent = elem;
|
2017-12-16 17:54:53 +01:00
|
|
|
(elem.externalIdentifier = externalIdentifier).parent = elem;
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createInterfaceDeclaration(identifier: IdentifierExpression, extendsType: TypeNode | null, members: DeclarationStatement[], modifiers: Modifier[] | null, range: Range): InterfaceDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new InterfaceDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.extendsType = extendsType)
|
|
|
|
(<TypeNode>extendsType).parent = stmt;
|
|
|
|
for (var i = 0, k = (stmt.members = members).length; i < k; ++i)
|
|
|
|
members[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createFieldDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FieldDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new FieldDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.type = type)
|
|
|
|
(<TypeNode>type).parent = stmt;
|
|
|
|
if (stmt.initializer = initializer)
|
|
|
|
(<Expression>initializer).parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (var i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createForStatement(initializer: Statement | null, condition: Expression | null, incrementor: Expression | null, statement: Statement, range: Range): ForStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ForStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.initializer = initializer)
|
|
|
|
(<Statement>initializer).parent = stmt;
|
|
|
|
if (stmt.condition = condition)
|
|
|
|
(<Expression>condition).parent = stmt;
|
|
|
|
if (stmt.incrementor = incrementor)
|
|
|
|
(<Expression>incrementor).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
(stmt.statement = statement).parent = stmt;
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static createTypeParameter(identifier: IdentifierExpression, extendsType: TypeNode | null, range: Range): TypeParameter {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new TypeParameter();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
|
|
|
(elem.identifier = identifier).parent = elem;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (elem.extendsType = extendsType)
|
|
|
|
(<TypeNode>extendsType).parent = elem;
|
2017-12-16 17:54:53 +01:00
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
static createParameter(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, isRest: bool, range: Range): Parameter {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new Parameter();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(elem.name = identifier).parent = elem;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (elem.type = type)
|
|
|
|
(<TypeNode>type).parent = elem;
|
|
|
|
if (elem.initializer = initializer)
|
|
|
|
(<Expression>initializer).parent = elem;
|
2017-12-18 03:46:36 +01:00
|
|
|
elem.isRest = isRest;
|
2017-12-16 17:54:53 +01:00
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createFunctionDeclaration(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FunctionDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new FunctionDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i)
|
|
|
|
typeParameters[i].parent = stmt;
|
|
|
|
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i)
|
|
|
|
parameters[i].parent = stmt;
|
|
|
|
if (stmt.returnType = returnType)
|
|
|
|
(<TypeNode>returnType).parent = stmt;
|
|
|
|
if (stmt.statements = statements)
|
|
|
|
for (i = 0, k = (<Statement[]>statements).length; i < k; ++i)
|
|
|
|
(<Statement[]>statements)[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createMethodDeclaration(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): MethodDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new MethodDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i)
|
|
|
|
typeParameters[i].parent = stmt;
|
|
|
|
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i)
|
|
|
|
parameters[i].parent = stmt;
|
|
|
|
if (stmt.returnType = returnType)
|
|
|
|
(<TypeNode>returnType).parent = stmt;
|
|
|
|
if (stmt.statements = statements)
|
|
|
|
for (i = 0, k = (<Statement[]>statements).length; i < k; ++i)
|
|
|
|
(<Statement[]>statements)[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static createModifier(kind: ModifierKind, range: Range): Modifier {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new Modifier();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
|
|
|
elem.modifierKind = kind;
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createNamespaceDeclaration(identifier: IdentifierExpression, members: Statement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): NamespaceDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new NamespaceDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.name = identifier).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.members = members).length; i < k; ++i)
|
|
|
|
members[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createReturnStatement(expression: Expression | null, range: Range): ReturnStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ReturnStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.value = expression)
|
|
|
|
(<Expression>expression).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createSwitchStatement(expression: Expression, cases: SwitchCase[], range: Range): SwitchStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new SwitchStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.condition = expression).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i: i32 = 0, k: i32 = (stmt.cases = cases).length; i < k; ++i)
|
|
|
|
cases[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static createSwitchCase(label: Expression | null, statements: Statement[], range: Range): SwitchCase {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new SwitchCase();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (elem.label = label)
|
|
|
|
(<Expression>label).parent = elem;
|
|
|
|
for (var i: i32 = 0, k: i32 = (elem.statements = statements).length; i < k; ++i)
|
|
|
|
statements[i].parent = elem;
|
2017-12-16 17:54:53 +01:00
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createThrowStatement(expression: Expression, range: Range): ThrowStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new ThrowStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-18 03:46:36 +01:00
|
|
|
(stmt.value = expression).parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createTryStatement(statements: Statement[], catchVariable: IdentifierExpression | null, catchStatements: Statement[] | null, finallyStatements: Statement[] | null, range: Range): TryStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new TryStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.statements = statements).length; i < k; ++i)
|
|
|
|
statements[i].parent = stmt;
|
|
|
|
if (stmt.catchVariable = catchVariable)
|
|
|
|
(<IdentifierExpression>catchVariable).parent = stmt;
|
|
|
|
if (stmt.catchStatements = catchStatements)
|
|
|
|
for (i = 0, k = (<Statement[]>catchStatements).length; i < k; ++i)
|
|
|
|
(<Statement[]>catchStatements)[i].parent = stmt;
|
|
|
|
if (stmt.finallyStatements = finallyStatements)
|
|
|
|
for (i = 0, k = (<Statement[]>finallyStatements).length; i < k; ++i)
|
|
|
|
(<Statement[]>finallyStatements)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:49:15 +01:00
|
|
|
static createTypeDeclaration(identifier: IdentifierExpression, alias: TypeNode, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): TypeDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new TypeDeclaration();
|
2017-12-19 17:49:15 +01:00
|
|
|
stmt.range = range;
|
|
|
|
(stmt.name = identifier).parent = stmt;
|
|
|
|
(stmt.alias = alias).parent = stmt;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (var i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-19 17:49:15 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createVariableStatement(declarations: VariableDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new VariableStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (stmt.declarations = declarations).length; i < k; ++i)
|
|
|
|
declarations[i].parent = stmt;
|
|
|
|
if (stmt.modifiers = modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i)
|
|
|
|
(<Modifier[]>modifiers)[i].parent = stmt;
|
|
|
|
if (stmt.decorators = decorators)
|
|
|
|
for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i)
|
|
|
|
(<Decorator[]>decorators)[i].parent = stmt;
|
2017-12-16 17:54:53 +01:00
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:49:15 +01:00
|
|
|
static createVariableDeclaration(name: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableDeclaration {
|
2017-12-28 04:09:40 +01:00
|
|
|
var elem = new VariableDeclaration();
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.range = range;
|
2017-12-19 17:49:15 +01:00
|
|
|
(elem.name = name).parent = elem;
|
2017-12-28 04:09:40 +01:00
|
|
|
if (elem.type = type)
|
|
|
|
(<TypeNode>type).parent = elem;
|
|
|
|
if (elem.initializer = initializer)
|
|
|
|
(<Expression>initializer).parent = elem;
|
2017-12-16 17:54:53 +01:00
|
|
|
elem.modifiers = modifiers;
|
|
|
|
elem.decorators = decorators;
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
static createWhileStatement(condition: Expression, statement: Statement, range: Range): WhileStatement {
|
2017-12-28 04:09:40 +01:00
|
|
|
var stmt = new WhileStatement();
|
2017-12-16 17:54:53 +01:00
|
|
|
stmt.range = range;
|
|
|
|
(stmt.condition = condition).parent = stmt;
|
|
|
|
(stmt.statement = statement).parent = stmt;
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// types
|
|
|
|
|
|
|
|
/** Represents a type annotation. */
|
|
|
|
export class TypeNode extends Node {
|
|
|
|
|
|
|
|
kind = NodeKind.TYPE;
|
|
|
|
|
|
|
|
/** Identifier reference. */
|
|
|
|
identifier: IdentifierExpression;
|
|
|
|
/** Type argument references. */
|
|
|
|
typeArguments: TypeNode[];
|
|
|
|
/** Whether nullable or not. */
|
|
|
|
isNullable: bool;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.identifier.serialize(sb);
|
|
|
|
if (this.typeArguments.length) {
|
|
|
|
sb.push("<");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.typeArguments.length; i < k; ++i) {
|
2017-12-16 17:54:53 +01:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.typeArguments[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (this.isNullable)
|
|
|
|
sb.push(" | null");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Represents a type parameter. */
|
|
|
|
export class TypeParameter extends Node {
|
|
|
|
|
|
|
|
kind = NodeKind.TYPEPARAMETER;
|
|
|
|
|
|
|
|
/** Identifier reference. */
|
|
|
|
identifier: IdentifierExpression;
|
|
|
|
/** Extended type reference, if any. */
|
|
|
|
extendsType: TypeNode | null;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.identifier.serialize(sb);
|
|
|
|
if (this.extendsType) {
|
|
|
|
sb.push(" extends ");
|
|
|
|
(<TypeNode>this.extendsType).serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// expressions
|
|
|
|
|
|
|
|
/** Base class of all expression nodes. */
|
|
|
|
export abstract class Expression extends Node { }
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an identifier expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class IdentifierExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.IDENTIFIER;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Textual name. */
|
2017-12-16 17:54:53 +01:00
|
|
|
name: string;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push(this.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Indicates the kind of a literal. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export const enum LiteralKind {
|
|
|
|
FLOAT,
|
|
|
|
INTEGER,
|
|
|
|
STRING,
|
|
|
|
REGEXP,
|
|
|
|
ARRAY,
|
|
|
|
OBJECT
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Base class of all literal expressions. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export abstract class LiteralExpression extends Expression {
|
2017-12-18 03:46:36 +01:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
kind = NodeKind.LITERAL;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Specific literal kind. */
|
2017-12-16 17:54:53 +01:00
|
|
|
literalKind: LiteralKind;
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `[]` literal expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class ArrayLiteralExpression extends LiteralExpression {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
// kind = NodeKind.LITERAL
|
2017-12-16 17:54:53 +01:00
|
|
|
literalKind = LiteralKind.ARRAY;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Nested element expressions. */
|
2017-12-16 17:54:53 +01:00
|
|
|
elementExpressions: (Expression | null)[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("[");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.elementExpressions.length; i < k; ++i) {
|
2017-12-16 17:54:53 +01:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
if (this.elementExpressions[i])
|
|
|
|
(<Expression>this.elementExpressions[i]).serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push("]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Indicates the kind of an assertion. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export const enum AssertionKind {
|
|
|
|
PREFIX,
|
|
|
|
AS
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an assertion expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class AssertionExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.ASSERTION;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Specific kind of this assertion. */
|
2017-12-16 17:54:53 +01:00
|
|
|
assertionKind: AssertionKind;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Expression being asserted. */
|
2017-12-16 17:54:53 +01:00
|
|
|
expression: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Target type. */
|
2017-12-16 17:54:53 +01:00
|
|
|
toType: TypeNode;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
if (this.assertionKind == AssertionKind.PREFIX) {
|
|
|
|
sb.push("<");
|
|
|
|
this.toType.serialize(sb);
|
|
|
|
sb.push(">");
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
} else {
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
sb.push(" as ");
|
|
|
|
this.toType.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a binary expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class BinaryExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.BINARY;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Operator token. */
|
2017-12-16 17:54:53 +01:00
|
|
|
operator: Token;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Left-hand side expression */
|
2017-12-16 17:54:53 +01:00
|
|
|
left: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Right-hand side expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
right: Expression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.left.serialize(sb);
|
|
|
|
sb.push(" ");
|
2017-12-24 03:19:47 +01:00
|
|
|
sb.push(Token.operatorToString(this.operator));
|
2017-12-16 17:54:53 +01:00
|
|
|
sb.push(" ");
|
|
|
|
this.right.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a call expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class CallExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.CALL;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Called expression. Usually an identifier or property access expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
expression: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Provided type arguments. */
|
2018-01-01 20:27:21 +01:00
|
|
|
typeArguments: TypeNode[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Provided arguments. */
|
2017-12-16 17:54:53 +01:00
|
|
|
arguments: Expression[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.expression.serialize(sb);
|
2018-01-01 20:27:21 +01:00
|
|
|
var k: i32;
|
|
|
|
if (this.typeArguments && (k = this.typeArguments.length)) {
|
2017-12-16 17:54:53 +01:00
|
|
|
sb.push("<");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0; i < k; ++i) {
|
2017-12-16 17:54:53 +01:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.typeArguments[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(">(");
|
|
|
|
} else
|
|
|
|
sb.push("(");
|
|
|
|
for (i = 0, k = this.arguments.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.arguments[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-05 01:55:59 +01:00
|
|
|
/** Represents a comma expression composed of multiple sequential expressions. */
|
|
|
|
export class CommaExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.COMMA;
|
|
|
|
|
|
|
|
/** Sequential expressions. */
|
|
|
|
expressions: Expression[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.expressions[0].serialize(sb);
|
|
|
|
for (var i = 1, k = this.expressions.length; i < k; ++i) {
|
|
|
|
sb.push(",");
|
|
|
|
this.expressions[i].serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `constructor` expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class ConstructorExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.CONSTRUCTOR;
|
2017-12-16 02:27:39 +01:00
|
|
|
name = "this";
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an element access expression, e.g., array access. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ElementAccessExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.ELEMENTACCESS;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Expression being accessed. */
|
2017-09-28 13:08:25 +02:00
|
|
|
expression: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Element of the expression being accessed. */
|
2017-09-28 13:08:25 +02:00
|
|
|
elementExpression: Expression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
sb.push("[");
|
|
|
|
this.elementExpression.serialize(sb);
|
|
|
|
sb.push("]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a float literal expression. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class FloatLiteralExpression extends LiteralExpression {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
// kind = NodeKind.LITERAL
|
2017-09-28 13:08:25 +02:00
|
|
|
literalKind = LiteralKind.FLOAT;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Float value. */
|
2017-09-28 13:08:25 +02:00
|
|
|
value: f64;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-11 02:03:15 +01:00
|
|
|
sb.push(this.value.toString(10));
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an integer literal expression. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class IntegerLiteralExpression extends LiteralExpression {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
// kind = NodeKind.LITERAL
|
2017-09-28 13:08:25 +02:00
|
|
|
literalKind = LiteralKind.INTEGER;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Integer value. */
|
2017-09-28 13:08:25 +02:00
|
|
|
value: I64;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push(this.value.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `new` expression. Like a call but with its own kind. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class NewExpression extends CallExpression {
|
|
|
|
|
|
|
|
kind = NodeKind.NEW;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("new ");
|
|
|
|
super.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `null` expression. */
|
2017-10-07 14:29:43 +02:00
|
|
|
export class NullExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.NULL;
|
|
|
|
name = "null";
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a parenthesized expression. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ParenthesizedExpression extends Expression {
|
|
|
|
|
|
|
|
kind = NodeKind.PARENTHESIZED;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Expression in parenthesis. */
|
2017-09-28 13:08:25 +02:00
|
|
|
expression: Expression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("(");
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
sb.push(")");
|
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a property access expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class PropertyAccessExpression extends Expression {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
kind = NodeKind.PROPERTYACCESS;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Expression being accessed. */
|
2017-12-16 17:54:53 +01:00
|
|
|
expression: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Property of the expression being accessed. */
|
2017-12-16 17:54:53 +01:00
|
|
|
property: IdentifierExpression;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
sb.push(".");
|
|
|
|
this.property.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a regular expression literal expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class RegexpLiteralExpression extends LiteralExpression {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
// kind = NodeKind.LITERAL
|
2017-12-16 17:54:53 +01:00
|
|
|
literalKind = LiteralKind.REGEXP;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
2018-01-07 15:07:46 +01:00
|
|
|
/** Regular expression pattern. */
|
|
|
|
pattern: string;
|
|
|
|
/** Regular expression modifiers. */
|
|
|
|
modifiers: string;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
serialize(sb: string[]): void {
|
2018-01-07 15:07:46 +01:00
|
|
|
sb.push("/");
|
|
|
|
sb.push(this.pattern);
|
|
|
|
sb.push("/");
|
|
|
|
sb.push(this.modifiers);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a ternary expression, i.e., short if notation. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class TernaryExpression extends Expression {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
kind = NodeKind.TERNARY;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Condition expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
condition: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Expression executed when condition is `true`. */
|
2017-12-16 17:54:53 +01:00
|
|
|
ifThen: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Expression executed when condition is `false`. */
|
2017-12-16 17:54:53 +01:00
|
|
|
ifElse: Expression;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.condition.serialize(sb);
|
|
|
|
sb.push(" ? ");
|
|
|
|
this.ifThen.serialize(sb);
|
|
|
|
sb.push(" : ");
|
|
|
|
this.ifElse.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a string literal expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class StringLiteralExpression extends LiteralExpression {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
literalKind = LiteralKind.STRING;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** String value without quotes. */
|
2017-12-16 17:54:53 +01:00
|
|
|
value: string;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
serialize(sb: string[]): void {
|
2017-12-29 04:38:39 +01:00
|
|
|
sb.push(stringToLiteral(this.value));
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `super` expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class SuperExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.SUPER;
|
|
|
|
name = "super";
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `this` expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class ThisExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.THIS;
|
|
|
|
name = "this";
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `true` expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class TrueExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.TRUE;
|
|
|
|
name = "true";
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `false` expression. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class FalseExpression extends IdentifierExpression {
|
|
|
|
kind = NodeKind.FALSE;
|
|
|
|
name = "false";
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Base class of all unary expressions. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export abstract class UnaryExpression extends Expression {
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
// kind varies
|
|
|
|
|
|
|
|
/** Operator token. */
|
2017-12-16 17:54:53 +01:00
|
|
|
operator: Token;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Operand expression. */
|
|
|
|
operand: Expression;
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a unary postfix expression, e.g. a postfix increment. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class UnaryPostfixExpression extends UnaryExpression {
|
|
|
|
|
|
|
|
kind = NodeKind.UNARYPOSTFIX;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
this.operand.serialize(sb);
|
2017-12-16 17:54:53 +01:00
|
|
|
switch (this.operator) {
|
|
|
|
case Token.PLUS_PLUS: sb.push("++"); break;
|
|
|
|
case Token.MINUS_MINUS: sb.push("--"); break;
|
|
|
|
default: sb.push("INVALID"); break;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-12-16 17:54:53 +01:00
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a unary prefix expression, e.g. a negation. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export class UnaryPrefixExpression extends UnaryExpression {
|
|
|
|
|
|
|
|
kind = NodeKind.UNARYPREFIX;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-24 03:19:47 +01:00
|
|
|
sb.push(Token.operatorToString(this.operator));
|
2017-12-18 03:46:36 +01:00
|
|
|
this.operand.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-16 17:54:53 +01:00
|
|
|
// statements
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Indicates the specific kind of a modifier. */
|
2017-12-16 17:54:53 +01:00
|
|
|
export enum ModifierKind {
|
|
|
|
ASYNC,
|
|
|
|
CONST,
|
|
|
|
DECLARE,
|
|
|
|
EXPORT,
|
|
|
|
IMPORT,
|
|
|
|
STATIC,
|
|
|
|
ABSTRACT,
|
|
|
|
PUBLIC,
|
|
|
|
PRIVATE,
|
|
|
|
PROTECTED,
|
|
|
|
READONLY,
|
|
|
|
GET,
|
|
|
|
SET,
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Base class of all statement nodes. */
|
|
|
|
export abstract class Statement extends Node { }
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** A top-level source node. */
|
2017-10-02 12:52:15 +02:00
|
|
|
export class Source extends Node {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
kind = NodeKind.SOURCE;
|
|
|
|
parent = null;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Path as provided to the parser. */
|
2017-09-28 13:08:25 +02:00
|
|
|
path: string;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Normalized path. */
|
2017-10-02 12:52:15 +02:00
|
|
|
normalizedPath: string;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Path used internally. */
|
2017-10-19 18:55:27 +02:00
|
|
|
internalPath: string;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Contained statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statements: Statement[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Full source text. */
|
2017-10-02 12:52:15 +02:00
|
|
|
text: string;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Tokenizer reference. */
|
2017-10-02 12:52:15 +02:00
|
|
|
tokenizer: Tokenizer | null = null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Whether an entry file or not. */
|
2017-10-02 12:52:15 +02:00
|
|
|
isEntry: bool;
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Constructs a new source node. */
|
2017-11-17 14:33:51 +01:00
|
|
|
constructor(path: string, text: string, isEntry: bool = false) {
|
2017-10-02 12:52:15 +02:00
|
|
|
super();
|
|
|
|
this.path = path;
|
|
|
|
this.normalizedPath = normalizePath(path, true);
|
2017-10-19 18:55:27 +02:00
|
|
|
this.internalPath = mangleInternalPath(this.normalizedPath);
|
2017-10-02 12:52:15 +02:00
|
|
|
this.statements = new Array();
|
|
|
|
this.range = new Range(this, 0, text.length);
|
|
|
|
this.text = text;
|
|
|
|
this.isEntry = isEntry;
|
|
|
|
}
|
|
|
|
|
2017-09-28 13:08:25 +02:00
|
|
|
serialize(sb: string[]): void {
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i: i32 = 0, k: i32 = this.statements.length; i < k; ++i) {
|
|
|
|
this.statements[i].serialize(sb);
|
2017-12-23 13:48:04 +01:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Base class of all declaration statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export abstract class DeclarationStatement extends Statement {
|
2017-10-11 17:03:22 +02:00
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
// kind varies
|
|
|
|
|
|
|
|
/** Simple name being declared. */
|
|
|
|
name: IdentifierExpression;
|
|
|
|
/** Array of modifiers. */
|
2017-10-11 17:03:22 +02:00
|
|
|
modifiers: Modifier[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Array of decorators. */
|
2017-12-08 04:03:44 +01:00
|
|
|
decorators: Decorator[] | null = null;
|
2017-10-11 17:03:22 +02:00
|
|
|
|
2017-10-19 18:55:27 +02:00
|
|
|
protected _cachedInternalName: string | null = null;
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Gets the mangled internal name of this declaration. */
|
2017-10-19 18:55:27 +02:00
|
|
|
get internalName(): string { return this._cachedInternalName === null ? this._cachedInternalName = mangleInternalName(this) : this._cachedInternalName; }
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Base class of all variable-like declaration statements with a type and initializer. */
|
2017-10-19 18:55:27 +02:00
|
|
|
export abstract class VariableLikeDeclarationStatement extends DeclarationStatement {
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
// kind varies
|
|
|
|
|
|
|
|
/** Variable type. */
|
2017-10-19 18:55:27 +02:00
|
|
|
type: TypeNode | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Variable initializer. */
|
2017-10-19 18:55:27 +02:00
|
|
|
initializer: Expression | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a block statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class BlockStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.BLOCK;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Contained statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statements: Statement[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("{\n");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.statements.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.statements[i].serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `break` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class BreakStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.BREAK;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Target label, if applicable. */
|
2017-09-28 13:08:25 +02:00
|
|
|
label: IdentifierExpression | null;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
if (this.label) {
|
|
|
|
sb.push("break ");
|
2017-12-11 02:03:15 +01:00
|
|
|
(<IdentifierExpression>this.label).serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
} else
|
|
|
|
sb.push("break");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `class` declaration. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ClassDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.CLASS;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Accepted type parameters. */
|
2017-09-28 13:08:25 +02:00
|
|
|
typeParameters: TypeParameter[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Base class type being extended. */
|
2017-09-28 13:08:25 +02:00
|
|
|
extendsType: TypeNode | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Interface types being implemented. */
|
2017-09-28 13:08:25 +02:00
|
|
|
implementsTypes: TypeNode[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Class member declarations. */
|
2017-09-28 13:08:25 +02:00
|
|
|
members: DeclarationStatement[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("class ");
|
2017-12-18 03:46:36 +01:00
|
|
|
sb.push(this.name.name);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.typeParameters.length) {
|
|
|
|
sb.push("<");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.typeParameters.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.typeParameters[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (this.extendsType) {
|
|
|
|
sb.push(" extends ");
|
|
|
|
this.extendsType.serialize(sb);
|
|
|
|
}
|
|
|
|
if (this.implementsTypes.length) {
|
|
|
|
sb.push(" implements ");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.implementsTypes.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.implementsTypes[i].serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sb.push(" {\n");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.members.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.members[i].serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `continue` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ContinueStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.CONTINUE;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Target label, if applicable. */
|
2017-09-28 13:08:25 +02:00
|
|
|
label: IdentifierExpression | null;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
if (this.label) {
|
|
|
|
sb.push("continue ");
|
2017-10-11 17:03:22 +02:00
|
|
|
(<IdentifierExpression>this.label).serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
} else
|
|
|
|
sb.push("continue");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-06 10:20:38 +01:00
|
|
|
/** Built-in decorator kinds. */
|
|
|
|
export const enum DecoratorKind {
|
|
|
|
CUSTOM,
|
|
|
|
GLOBAL,
|
|
|
|
OPERATOR,
|
|
|
|
STRUCT,
|
|
|
|
SIZE
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Depresents a decorator. */
|
2017-12-08 04:03:44 +01:00
|
|
|
export class Decorator extends Statement {
|
2017-10-02 12:52:15 +02:00
|
|
|
|
|
|
|
kind = NodeKind.DECORATOR;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Name expression. */
|
|
|
|
name: Expression;
|
|
|
|
/** Argument expressions. */
|
2018-01-01 20:27:21 +01:00
|
|
|
arguments: Expression[] | null;
|
2018-01-06 10:20:38 +01:00
|
|
|
/** Built-in kind, if applicable. */
|
|
|
|
decoratorKind: DecoratorKind;
|
2017-10-02 12:52:15 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("@");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2018-01-01 20:27:21 +01:00
|
|
|
if (this.arguments) {
|
|
|
|
sb.push("(");
|
|
|
|
for (var i = 0, k = this.arguments.length; i < k; ++i) {
|
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.arguments[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(")");
|
2017-10-02 12:52:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `do` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class DoStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.DO;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Statement being looped over. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statement: Statement;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Condition when to repeat. */
|
2017-09-28 13:08:25 +02:00
|
|
|
condition: Expression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("do ");
|
|
|
|
this.statement.serialize(sb);
|
|
|
|
if (this.statement.kind == NodeKind.BLOCK)
|
|
|
|
sb.push(" while (");
|
|
|
|
else
|
|
|
|
sb.push(";\nwhile (");
|
|
|
|
this.condition.serialize(sb);
|
|
|
|
sb.push(")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an empty statement, i.e., a semicolon terminating nothing. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class EmptyStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.EMPTY;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `enum` declaration. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class EnumDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.ENUM;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Enum value declarations. */
|
|
|
|
values: EnumValueDeclaration[];
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
2017-10-11 17:03:22 +02:00
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("enum ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" {\n");
|
2017-12-18 03:46:36 +01:00
|
|
|
for (i = 0, k = this.values.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.values[i].serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
sb.push("\n}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a value of an `enum` declaration. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class EnumValueDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.ENUMVALUE;
|
2017-10-11 17:03:22 +02:00
|
|
|
modifiers = null;
|
2017-12-18 03:46:36 +01:00
|
|
|
// name is inherited
|
|
|
|
|
|
|
|
/** Value expression. */
|
2017-09-28 13:08:25 +02:00
|
|
|
value: Expression | null;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.value) {
|
|
|
|
sb.push(" = ");
|
|
|
|
(<Expression>this.value).serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `export import` statement of an interface. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ExportImportStatement extends Node {
|
|
|
|
|
|
|
|
kind = NodeKind.EXPORTIMPORT;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Identifier being imported. */
|
2017-09-28 13:08:25 +02:00
|
|
|
identifier: IdentifierExpression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Identifier being exported. */
|
|
|
|
externalIdentifier: IdentifierExpression;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("export import ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.externalIdentifier.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" = ");
|
|
|
|
this.identifier.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a member of an `export` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ExportMember extends Node {
|
|
|
|
|
2017-09-29 17:25:02 +02:00
|
|
|
kind = NodeKind.EXPORTMEMBER;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Identifier being exported. */
|
2017-09-28 13:08:25 +02:00
|
|
|
identifier: IdentifierExpression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Identifier seen when imported again. */
|
2017-09-29 17:25:02 +02:00
|
|
|
externalIdentifier: IdentifierExpression;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.identifier.serialize(sb);
|
2017-09-29 17:25:02 +02:00
|
|
|
if (this.externalIdentifier.name != this.identifier.name) {
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" as ");
|
2017-09-29 17:25:02 +02:00
|
|
|
(<IdentifierExpression>this.externalIdentifier).serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `export` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ExportStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.EXPORT;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Array of modifiers. */
|
2017-10-11 17:03:22 +02:00
|
|
|
modifiers: Modifier[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Array of members. */
|
2017-09-28 13:08:25 +02:00
|
|
|
members: ExportMember[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Path being exported from, if applicable. */
|
2017-10-11 17:03:22 +02:00
|
|
|
path: StringLiteralExpression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Normalized path, if `path` is set. */
|
2017-10-02 12:52:15 +02:00
|
|
|
normalizedPath: string | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Mangled internal path being referenced, if `path` is set. */
|
2017-10-19 18:55:27 +02:00
|
|
|
internalPath: string | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
2017-10-11 17:03:22 +02:00
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("export {\n");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.members.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
|
|
|
this.members[i].serialize(sb);
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.path) {
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n} from ");
|
2017-10-11 17:03:22 +02:00
|
|
|
this.path.serialize(sb);
|
|
|
|
} else
|
|
|
|
sb.push("\n}");
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an expression statement, i.e., an expression being used as a statement */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ExpressionStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.EXPRESSION;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Expression being used as a statement.*/
|
2017-09-28 13:08:25 +02:00
|
|
|
expression: Expression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.expression.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a field declaration within a `class`. */
|
2017-10-19 18:55:27 +02:00
|
|
|
export class FieldDeclaration extends VariableLikeDeclarationStatement {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
kind = NodeKind.FIELD;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.type) {
|
|
|
|
sb.push(": ");
|
|
|
|
(<TypeNode>this.type).serialize(sb);
|
|
|
|
}
|
|
|
|
if (this.initializer) {
|
|
|
|
sb.push(" = ");
|
|
|
|
(<Expression>this.initializer).serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `for` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ForStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.FOR;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Initializer statement, if present. Either a {@link VariableStatement} or {@link ExpressionStatement}. */
|
2017-09-28 13:08:25 +02:00
|
|
|
initializer: Statement | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Condition expression, if present. */
|
2017-09-28 13:08:25 +02:00
|
|
|
condition: Expression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Incrementor expression, if present. */
|
2017-09-28 13:08:25 +02:00
|
|
|
incrementor: Expression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Statement being looped over. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statement: Statement;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("for (");
|
|
|
|
if (this.initializer)
|
|
|
|
this.initializer.serialize(sb);
|
|
|
|
if (this.condition) {
|
|
|
|
sb.push("; ");
|
|
|
|
this.condition.serialize(sb);
|
|
|
|
} else
|
|
|
|
sb.push(";");
|
|
|
|
if (this.incrementor) {
|
|
|
|
sb.push("; ");
|
|
|
|
this.incrementor.serialize(sb);
|
|
|
|
} else
|
|
|
|
sb.push(";");
|
|
|
|
sb.push(") ");
|
|
|
|
this.statement.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `function` declaration. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class FunctionDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.FUNCTION;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Accepted type parameters. */
|
2017-09-28 13:08:25 +02:00
|
|
|
typeParameters: TypeParameter[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Accepted parameters. */
|
2017-09-28 13:08:25 +02:00
|
|
|
parameters: Parameter[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Return type. */
|
2017-09-28 13:08:25 +02:00
|
|
|
returnType: TypeNode | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Contained statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statements: Statement[] | null;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("function ");
|
|
|
|
this.serializeCommon(sb);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected serializeCommon(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.typeParameters.length) {
|
|
|
|
sb.push("<");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.typeParameters.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.typeParameters[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
sb.push("(");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.parameters.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.parameters[i].serialize(sb);
|
|
|
|
}
|
2017-12-14 11:55:35 +01:00
|
|
|
if (this.returnType && !hasModifier(ModifierKind.SET, this.modifiers)) {
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("): ");
|
|
|
|
(<TypeNode>this.returnType).serialize(sb);
|
|
|
|
} else
|
|
|
|
sb.push(")");
|
|
|
|
if (this.statements) {
|
|
|
|
sb.push(" {\n");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = (<Statement[]>this.statements).length; i < k; ++i) {
|
2017-12-28 04:09:40 +01:00
|
|
|
var statement: Statement = (<Statement[]>this.statements)[i];
|
2017-09-28 13:08:25 +02:00
|
|
|
statement.serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `if` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class IfStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.IF;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Condition. */
|
2017-09-28 13:08:25 +02:00
|
|
|
condition: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Statement executed when condition is `true`. */
|
|
|
|
ifTrue: Statement;
|
|
|
|
/** Statement executed when condition is `false`. */
|
|
|
|
ifFalse: Statement | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("if (");
|
|
|
|
this.condition.serialize(sb);
|
|
|
|
sb.push(") ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.ifTrue.serialize(sb);
|
|
|
|
if (this.ifTrue.kind != NodeKind.BLOCK)
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(";\n");
|
2017-12-18 03:46:36 +01:00
|
|
|
if (this.ifFalse) {
|
|
|
|
if (this.ifTrue.kind == NodeKind.BLOCK)
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" else ");
|
|
|
|
else
|
|
|
|
sb.push("else ");
|
2017-12-18 03:46:36 +01:00
|
|
|
(<Statement>this.ifFalse).serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `import` declaration, a single member within an {@link ImportStatement}. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ImportDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.IMPORTDECLARATION;
|
2017-10-11 17:03:22 +02:00
|
|
|
modifiers = null;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Identifier being imported. */
|
2017-09-28 13:08:25 +02:00
|
|
|
externalIdentifier: IdentifierExpression;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
this.externalIdentifier.serialize(sb);
|
2017-12-18 03:46:36 +01:00
|
|
|
if (this.externalIdentifier != this.name) {
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" as ");
|
2017-12-18 03:46:36 +01:00
|
|
|
(<IdentifierExpression>this.name).serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `import` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ImportStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.IMPORT;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
2017-12-23 00:48:54 +01:00
|
|
|
/** Array of member declarations or `null` if an asterisk import. */
|
|
|
|
declarations: ImportDeclaration[] | null;
|
|
|
|
/** Name of the local namespace, if an asterisk import. */
|
|
|
|
namespaceName: IdentifierExpression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Path being imported from. */
|
2017-10-11 17:03:22 +02:00
|
|
|
path: StringLiteralExpression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Normalized path. */
|
2017-10-02 12:52:15 +02:00
|
|
|
normalizedPath: string;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Mangled internal path being referenced. */
|
2017-10-19 18:55:27 +02:00
|
|
|
internalPath: string;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2018-01-05 18:19:32 +01:00
|
|
|
sb.push("import ");
|
2017-12-23 00:48:54 +01:00
|
|
|
if (this.declarations) {
|
2018-01-05 18:19:32 +01:00
|
|
|
sb.push("{\n");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i: i32 = 0, k: i32 = this.declarations.length; i < k; ++i) {
|
2017-12-23 00:48:54 +01:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(",\n");
|
|
|
|
this.declarations[i].serialize(sb);
|
|
|
|
}
|
2018-01-05 18:19:32 +01:00
|
|
|
sb.push("\n} from ");
|
|
|
|
} else if (this.namespaceName) {
|
|
|
|
sb.push("* as ");
|
|
|
|
this.namespaceName.serialize(sb);
|
|
|
|
sb.push(" from ");
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
this.path.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents an `interfarce` declaration. */
|
2017-10-19 18:55:27 +02:00
|
|
|
export class InterfaceDeclaration extends ClassDeclaration {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
kind = NodeKind.INTERFACE;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = this.modifiers.length; i < k; ++i) {
|
|
|
|
this.modifiers[i].serialize(sb);
|
2017-10-11 17:03:22 +02:00
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("interface ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.typeParameters.length) {
|
|
|
|
sb.push("<");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.typeParameters.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
|
|
|
this.typeParameters[i].serialize(sb);
|
|
|
|
}
|
|
|
|
sb.push(">");
|
|
|
|
}
|
|
|
|
if (this.extendsType) {
|
|
|
|
sb.push(" extends ");
|
2017-12-28 04:09:40 +01:00
|
|
|
this.extendsType.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
sb.push(" {\n");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.members.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.members[i].serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a method declaration within a `class`. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class MethodDeclaration extends FunctionDeclaration {
|
|
|
|
|
|
|
|
kind = NodeKind.METHOD;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = this.modifiers.length; i < k; ++i) {
|
|
|
|
this.modifiers[i].serialize(sb);
|
2017-10-11 17:03:22 +02:00
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
super.serializeCommon(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `namespace` declaration. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class NamespaceDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.NAMESPACE;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Array of namespace members. */
|
2017-10-07 14:29:43 +02:00
|
|
|
members: Statement[];
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = this.modifiers.length; i < k; ++i) {
|
|
|
|
this.modifiers[i].serialize(sb);
|
2017-10-11 17:03:22 +02:00
|
|
|
sb.push(" ");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("namespace ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(" {\n");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.members.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.members[i].serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a function parameter. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class Parameter extends Node {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
kind = NodeKind.PARAMETER;
|
|
|
|
|
|
|
|
/** Parameter name. */
|
|
|
|
name: IdentifierExpression;
|
|
|
|
/** Parameter type. */
|
2017-09-28 13:08:25 +02:00
|
|
|
type: TypeNode | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Initializer expression, if present. */
|
2017-09-28 13:08:25 +02:00
|
|
|
initializer: Expression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Whether a rest parameter or not. */
|
|
|
|
isRest: bool;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
if (this.isRest)
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("...");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.type) {
|
|
|
|
sb.push(": ");
|
2017-12-28 04:09:40 +01:00
|
|
|
this.type.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
if (this.initializer) {
|
|
|
|
sb.push(" = ");
|
2017-12-28 04:09:40 +01:00
|
|
|
this.initializer.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a single modifier. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class Modifier extends Node {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
kind = NodeKind.MODIFIER;
|
|
|
|
|
|
|
|
/** Specific modifier kind. */
|
2017-09-28 13:08:25 +02:00
|
|
|
modifierKind: ModifierKind;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-16 17:54:53 +01:00
|
|
|
sb.push(this.toString());
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Returns the TypeScript representation of this modifier. */
|
2017-12-16 17:54:53 +01:00
|
|
|
toString(): string {
|
2017-09-28 13:08:25 +02:00
|
|
|
switch (this.modifierKind) {
|
2017-12-16 17:54:53 +01:00
|
|
|
case ModifierKind.ABSTRACT: return "abstract";
|
|
|
|
case ModifierKind.ASYNC: return "async";
|
|
|
|
case ModifierKind.CONST: return "const";
|
|
|
|
case ModifierKind.DECLARE: return "declare";
|
|
|
|
case ModifierKind.EXPORT: return "export";
|
|
|
|
case ModifierKind.GET: return "get";
|
|
|
|
case ModifierKind.IMPORT: return "import";
|
|
|
|
case ModifierKind.PRIVATE: return "private";
|
|
|
|
case ModifierKind.PROTECTED: return "protected";
|
|
|
|
case ModifierKind.PUBLIC: return "public";
|
|
|
|
case ModifierKind.READONLY: return "readonly";
|
|
|
|
case ModifierKind.SET: return "set";
|
|
|
|
case ModifierKind.STATIC: return "static";
|
2017-12-18 03:46:36 +01:00
|
|
|
default: assert(false); return "";
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `return` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ReturnStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.RETURN;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Value expression being returned, if present. */
|
|
|
|
value: Expression | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
if (this.value) {
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("return ");
|
2017-12-28 04:09:40 +01:00
|
|
|
this.value.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
} else
|
|
|
|
sb.push("return");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a single `case` within a `switch` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class SwitchCase extends Node {
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
kind = NodeKind.CASE;
|
|
|
|
|
|
|
|
/** Label expression. `null` indicates the default case. */
|
|
|
|
label: Expression | null;
|
|
|
|
/** Contained statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statements: Statement[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
if (this.label) {
|
|
|
|
sb.push("case ");
|
2017-12-28 04:09:40 +01:00
|
|
|
this.label.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(":\n");
|
|
|
|
} else
|
|
|
|
sb.push("default:\n");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.statements.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push("\n");
|
|
|
|
this.statements[i].serialize(sb);
|
2017-10-07 14:29:43 +02:00
|
|
|
if (builderEndsWith(sb, CharCode.CLOSEBRACE))
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push("\n");
|
|
|
|
else
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `switch` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class SwitchStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.SWITCH;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Condition expression. */
|
|
|
|
condition: Expression;
|
|
|
|
/** Contained cases. */
|
2017-09-28 13:08:25 +02:00
|
|
|
cases: SwitchCase[];
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("switch (");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.condition.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
sb.push(") {\n");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.cases.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.cases[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `throw` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class ThrowStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.THROW;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Value expression being thrown. */
|
|
|
|
value: Expression;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("throw ");
|
2017-12-18 03:46:36 +01:00
|
|
|
this.value.serialize(sb);
|
2017-11-17 14:33:51 +01:00
|
|
|
sb.push(";");
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `try` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class TryStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.TRY;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Contained statements. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statements: Statement[];
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Variable identifier for a caught exception, if a `catch` clause is present. */
|
2017-10-07 14:29:43 +02:00
|
|
|
catchVariable: IdentifierExpression | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Statements being executed when an exception has been caught, if a `catch` clause is present. */
|
2017-10-07 14:29:43 +02:00
|
|
|
catchStatements: Statement[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Statements being executed in any case, if a `finally` clause is present. */
|
2017-10-07 14:29:43 +02:00
|
|
|
finallyStatements: Statement[] | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("try {\n");
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.statements.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
this.statements[i].serialize(sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
2017-10-07 14:29:43 +02:00
|
|
|
if (this.catchVariable) {
|
|
|
|
sb.push("} catch (");
|
|
|
|
(<IdentifierExpression>this.catchVariable).serialize(sb);
|
|
|
|
sb.push(") {\n");
|
|
|
|
if (this.catchStatements)
|
|
|
|
for (i = 0, k = (<Statement[]>this.catchStatements).length; i < k; ++i) {
|
|
|
|
(<Statement[]>this.catchStatements)[i].serialize(sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.finallyStatements) {
|
|
|
|
sb.push("} finally {\n");
|
|
|
|
for (i = 0, k = (<Statement[]>this.finallyStatements).length; i < k; ++i) {
|
|
|
|
(<Statement[]>this.finallyStatements)[i].serialize(sb);
|
|
|
|
sb.push(";\n");
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
sb.push("}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 17:49:15 +01:00
|
|
|
/** Represents a `type` declaration. */
|
|
|
|
export class TypeDeclaration extends DeclarationStatement {
|
|
|
|
|
|
|
|
kind = NodeKind.TYPEDECLARATION;
|
|
|
|
|
|
|
|
/** Type being aliased. */
|
|
|
|
alias: TypeNode;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-19 17:49:15 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
|
|
|
if (this.modifiers)
|
|
|
|
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
|
|
|
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
|
|
|
sb.push(" ");
|
|
|
|
}
|
|
|
|
sb.push("type ");
|
|
|
|
this.name.serialize(sb);
|
|
|
|
sb.push(" = ");
|
|
|
|
this.alias.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a single variable declaration within a {@link VariableStatement}. */
|
2017-10-19 18:55:27 +02:00
|
|
|
export class VariableDeclaration extends VariableLikeDeclarationStatement {
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
kind = NodeKind.VARIABLEDECLARATION;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Array of modifiers. */
|
2017-12-02 18:37:59 +01:00
|
|
|
modifiers: Modifier[] | null;
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-18 03:46:36 +01:00
|
|
|
this.name.serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
if (this.type) {
|
|
|
|
sb.push(": ");
|
|
|
|
(<TypeNode>this.type).serialize(sb);
|
|
|
|
}
|
|
|
|
if (this.initializer) {
|
|
|
|
sb.push(" = ");
|
|
|
|
(<Expression>this.initializer).serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a variable statement, i.e., a `var`, `let` or `const` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class VariableStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.VARIABLE;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Array of modifiers. */
|
2017-10-11 17:03:22 +02:00
|
|
|
modifiers: Modifier[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Array of decorators. */
|
2017-12-08 04:03:44 +01:00
|
|
|
decorators: Decorator[] | null;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Array of member declarations. */
|
2017-10-02 12:52:15 +02:00
|
|
|
declarations: VariableDeclaration[];
|
2017-09-28 13:08:25 +02:00
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
2017-12-28 04:09:40 +01:00
|
|
|
var isConst = false;
|
2017-12-08 04:03:44 +01:00
|
|
|
if (this.decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = this.decorators.length; i < k; ++i) {
|
2017-12-08 04:03:44 +01:00
|
|
|
this.decorators[i].serialize(sb);
|
|
|
|
sb.push("\n");
|
|
|
|
}
|
2017-10-11 17:03:22 +02:00
|
|
|
if (this.modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (i = 0, k = this.modifiers.length; i < k; ++i) {
|
|
|
|
this.modifiers[i].serialize(sb);
|
2017-10-11 17:03:22 +02:00
|
|
|
sb.push(" ");
|
2017-12-28 04:09:40 +01:00
|
|
|
if (this.modifiers[i].modifierKind == ModifierKind.CONST)
|
2017-10-11 17:03:22 +02:00
|
|
|
isConst = true;
|
|
|
|
}
|
2017-09-28 13:08:25 +02:00
|
|
|
if (!isConst)
|
|
|
|
sb.push("let ");
|
2017-10-02 12:52:15 +02:00
|
|
|
for (i = 0, k = this.declarations.length; i < k; ++i) {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (i > 0)
|
|
|
|
sb.push(", ");
|
2017-10-02 12:52:15 +02:00
|
|
|
this.declarations[i].serialize(sb);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Represents a `while` statement. */
|
2017-09-28 13:08:25 +02:00
|
|
|
export class WhileStatement extends Statement {
|
|
|
|
|
|
|
|
kind = NodeKind.WHILE;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
/** Condition expression. */
|
2017-09-28 13:08:25 +02:00
|
|
|
condition: Expression;
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Statement being looped over. */
|
2017-09-28 13:08:25 +02:00
|
|
|
statement: Statement;
|
|
|
|
|
|
|
|
serialize(sb: string[]): void {
|
|
|
|
sb.push("while (");
|
|
|
|
this.condition.serialize(sb);
|
|
|
|
sb.push(") ");
|
|
|
|
this.statement.serialize(sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Cached unused modifiers for reuse. */
|
2017-12-28 04:09:40 +01:00
|
|
|
var reusableModifiers: Modifier[] | null = null;
|
2017-12-18 03:46:36 +01:00
|
|
|
|
|
|
|
export function setReusableModifiers(modifiers: Modifier[]) {
|
|
|
|
reusableModifiers = modifiers;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Creates a new modifiers array. */
|
|
|
|
export function createModifiers(): Modifier[] {
|
2017-12-28 04:09:40 +01:00
|
|
|
var ret: Modifier[];
|
2017-12-18 03:46:36 +01:00
|
|
|
if (reusableModifiers != null) {
|
|
|
|
ret = reusableModifiers;
|
|
|
|
reusableModifiers = null;
|
|
|
|
} else
|
|
|
|
ret = new Array(1);
|
|
|
|
ret.length = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Adds a modifier to a modifiers array. Creates and returns a new array if `null`. */
|
|
|
|
export function addModifier(modifier: Modifier, modifiers: Modifier[] | null): Modifier[] {
|
|
|
|
if (modifiers == null)
|
|
|
|
modifiers = createModifiers();
|
|
|
|
modifiers.push(modifier);
|
|
|
|
return modifiers;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Gets a specific modifier from the specified array of modifiers. */
|
|
|
|
export function getModifier(kind: ModifierKind, modifiers: Modifier[] | null): Modifier | null {
|
2017-10-11 17:03:22 +02:00
|
|
|
if (modifiers)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = modifiers.length; i < k; ++i)
|
2017-12-18 03:46:36 +01:00
|
|
|
if (modifiers[i].modifierKind == kind)
|
|
|
|
return modifiers[i];
|
|
|
|
return null;
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Tests whether a specific modifier exists in the specified array of modifiers. */
|
|
|
|
export function hasModifier(kind: ModifierKind, modifiers: Modifier[] | null): bool {
|
|
|
|
return getModifier(kind, modifiers) != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Gets a specific decorator within the specified decorators, if present. */
|
2018-01-06 10:20:38 +01:00
|
|
|
export function getFirstDecorator(name: string, decorators: Decorator[] | null): Decorator | null {
|
2017-12-16 02:27:39 +01:00
|
|
|
if (decorators)
|
2017-12-28 04:09:40 +01:00
|
|
|
for (var i = 0, k = decorators.length; i < k; ++i) {
|
|
|
|
var decorator = decorators[i];
|
|
|
|
var expression = decorator.name;
|
2017-12-16 02:27:39 +01:00
|
|
|
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).name == name)
|
|
|
|
return decorator;
|
|
|
|
}
|
2017-10-19 18:55:27 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Tests if a specific decorator is present within the specified decorators. */
|
2017-12-16 02:27:39 +01:00
|
|
|
export function hasDecorator(name: string, decorators: Decorator[] | null): bool {
|
2018-01-06 10:20:38 +01:00
|
|
|
return getFirstDecorator(name, decorators) != null;
|
2017-12-16 02:27:39 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Serializes the specified node to its TypeScript representation. */
|
|
|
|
export function serialize(node: Node): string {
|
2017-12-28 04:09:40 +01:00
|
|
|
var sb = new Array<string>(); // shared builder could grow too much
|
2017-09-28 13:08:25 +02:00
|
|
|
node.serialize(sb);
|
|
|
|
return sb.join("");
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Mangles a path to an internal path. */
|
2017-10-19 18:55:27 +02:00
|
|
|
export function mangleInternalPath(path: string): string {
|
2017-11-17 14:33:51 +01:00
|
|
|
// TODO: not necessary with current config
|
|
|
|
/* if (PATH_DELIMITER.charCodeAt(0) != CharCode.SLASH)
|
2017-10-19 18:55:27 +02:00
|
|
|
path = path.replace("/", PATH_DELIMITER);
|
|
|
|
if (PARENT_SUBST != "..")
|
2017-11-17 14:33:51 +01:00
|
|
|
path = path.replace("..", PARENT_SUBST); */
|
2017-10-19 18:55:27 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Mangles a declaration's name to an internal name. */
|
2017-10-11 17:03:22 +02:00
|
|
|
export function mangleInternalName(declaration: DeclarationStatement): string {
|
2017-12-28 04:09:40 +01:00
|
|
|
var name = declaration.name.name;
|
|
|
|
var parent = declaration.parent;
|
2017-12-13 23:24:13 +01:00
|
|
|
if (!parent)
|
2017-10-11 17:03:22 +02:00
|
|
|
return name;
|
2017-12-13 23:24:13 +01:00
|
|
|
if (declaration.kind == NodeKind.VARIABLEDECLARATION && parent.kind == NodeKind.VARIABLE) // skip over
|
|
|
|
if (!(parent = parent.parent))
|
|
|
|
return name;
|
|
|
|
if (parent.kind == NodeKind.CLASS)
|
|
|
|
return (<ClassDeclaration>parent).internalName + (hasModifier(ModifierKind.STATIC, declaration.modifiers) ? STATIC_DELIMITER : INSTANCE_DELIMITER) + name;
|
|
|
|
if (parent.kind == NodeKind.NAMESPACE || parent.kind == NodeKind.ENUM)
|
|
|
|
return (<DeclarationStatement>parent).internalName + STATIC_DELIMITER + name;
|
2017-10-19 18:55:27 +02:00
|
|
|
return declaration.range.source.internalPath + PATH_DELIMITER + name;
|
2017-10-11 17:03:22 +02:00
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Tests if the specified builder ends with the specified char code. */
|
2017-10-07 14:29:43 +02:00
|
|
|
function builderEndsWith(sb: string[], code: CharCode): bool {
|
2017-09-28 13:08:25 +02:00
|
|
|
if (sb.length) {
|
2017-12-28 04:09:40 +01:00
|
|
|
var last = sb[sb.length - 1];
|
2017-12-18 03:46:36 +01:00
|
|
|
return select<bool>(last.charCodeAt(last.length - 1) == code, false, last.length > 0);
|
2017-09-28 13:08:25 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-28 04:09:40 +01:00
|
|
|
|
2017-12-29 04:38:39 +01:00
|
|
|
/** Converts a string to its literal representation including quotes. */
|
2017-12-30 05:11:58 +01:00
|
|
|
export function stringToLiteral(str: string, singleQuoted: bool = false): string {
|
2017-12-29 04:38:39 +01:00
|
|
|
var ret = new Array<string>();
|
|
|
|
var off = 0;
|
|
|
|
for (var i = 0, k = str.length; i < k;) {
|
|
|
|
switch (str.charCodeAt(i)) {
|
|
|
|
|
|
|
|
case CharCode.NULL:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, off = i + 1));
|
|
|
|
ret.push("\\0");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.BACKSPACE:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
ret.push("\\b");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.TAB:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
ret.push("\\t");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.LINEFEED:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
ret.push("\\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.VERTICALTAB:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
ret.push("\\v");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.FORMFEED:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
off = ++i;
|
|
|
|
ret.push("\\f");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.CARRIAGERETURN:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
ret.push("\\r");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.DOUBLEQUOTE:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
ret.push("\\\"");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.SINGLEQUOTE:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
ret.push("\\'");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharCode.BACKSLASH:
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
|
|
|
ret.push("\\\\");
|
|
|
|
off = ++i;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++i;
|
|
|
|
break;
|
2017-12-28 04:09:40 +01:00
|
|
|
}
|
|
|
|
}
|
2017-12-30 05:11:58 +01:00
|
|
|
var quote = singleQuoted ? "'" : "\"";
|
2017-12-29 04:38:39 +01:00
|
|
|
if (off == 0) {
|
|
|
|
assert(ret.length == 0);
|
2017-12-30 05:11:58 +01:00
|
|
|
return quote + str + quote;
|
2017-12-29 04:38:39 +01:00
|
|
|
}
|
|
|
|
if (i > off)
|
|
|
|
ret.push(str.substring(off, i));
|
2017-12-30 05:11:58 +01:00
|
|
|
return quote + ret.join("") + quote;
|
2017-12-28 04:09:40 +01:00
|
|
|
}
|