mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 17:27:54 -05:00
Adds the TypeScript transformer
This commit is contained in:
16
Jakefile.js
16
Jakefile.js
@@ -42,6 +42,14 @@ var compilerSources = [
|
||||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/module/es6.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/es7.ts",
|
||||
"transformers/es6.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
@@ -67,6 +75,14 @@ var servicesSources = [
|
||||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/module/es6.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/es7.ts",
|
||||
"transformers/es6.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
|
||||
@@ -1838,6 +1838,12 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportKeyword:
|
||||
// This node is both ES6 and TypeScript syntax.
|
||||
transformFlags |= TransformFlags.AssertES6 | TransformFlags.TypeScript;
|
||||
break;
|
||||
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
|
||||
@@ -142,25 +142,44 @@ namespace ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
export function filter<T, U extends T>(array: T[], f: (x: T, i: number) => x is U): U[];
|
||||
export function filter<T>(array: T[], f: (x: T, i: number) => boolean): T[];
|
||||
export function filter<T>(array: T[], f: (x: T, i: number) => boolean): T[] {
|
||||
let result: T[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (const item of array) {
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
if (f(v, i)) {
|
||||
result.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
|
||||
export function map<T, U>(array: T[], f: (x: T, i: number) => U): U[] {
|
||||
let result: U[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (const v of array) {
|
||||
result.push(f(v));
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
result.push(f(v, i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function flatMap<T, U>(array: T[], f: (x: T, i: number) => U[]): U[] {
|
||||
let result: U[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
const ar = f(v, i);
|
||||
if (ar) {
|
||||
result = result.concat(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -212,15 +231,25 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function firstOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length > 0
|
||||
? array[0]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function singleOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length === 1
|
||||
? array[0]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of an array if non-empty, undefined otherwise.
|
||||
*/
|
||||
export function lastOrUndefined<T>(array: T[]): T {
|
||||
if (array.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return array[array.length - 1];
|
||||
return array && array.length > 0
|
||||
? array[array.length - 1]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -287,8 +287,12 @@ namespace ts {
|
||||
_i = 0x10000000, // Use/preference flag for '_i'
|
||||
}
|
||||
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
return printFiles(resolver, host, targetSourceFile);
|
||||
}
|
||||
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
export function legacyEmitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
// emit output for the __extends helper function
|
||||
const extendsHelper = `
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
|
||||
@@ -6,33 +6,88 @@ namespace ts {
|
||||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
function createNode(kind: SyntaxKind, location?: TextRange): Node {
|
||||
function createNode(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags): Node {
|
||||
const ConstructorForKind = kind === SyntaxKind.SourceFile
|
||||
? (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))
|
||||
: (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()));
|
||||
|
||||
return location
|
||||
const node = location
|
||||
? new ConstructorForKind(kind, location.pos, location.end)
|
||||
: new ConstructorForKind(kind, /*pos*/ -1, /*end*/ -1);
|
||||
|
||||
if (flags) {
|
||||
node.flags = flags;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createNodeArray<T extends Node>(elements?: T[], pos?: number, end?: number): NodeArray<T> {
|
||||
const array = <NodeArray<T>>(elements || []);
|
||||
array.pos = pos;
|
||||
array.end = end;
|
||||
export function createNodeArray<T extends Node>(elements?: T[], location?: TextRange): NodeArray<T> {
|
||||
if (elements) {
|
||||
if (isNodeArray(elements)) {
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
elements = [];
|
||||
}
|
||||
|
||||
const array = <NodeArray<T>>elements;
|
||||
if (location) {
|
||||
array.pos = location.pos;
|
||||
array.end = location.end;
|
||||
}
|
||||
else {
|
||||
array.pos = -1;
|
||||
array.end = -1;
|
||||
}
|
||||
|
||||
array.arrayKind = ArrayKind.NodeArray;
|
||||
return array;
|
||||
}
|
||||
|
||||
export function createModifiersArray(elements?: Modifier[], pos?: number, end?: number): ModifiersArray {
|
||||
const array = <ModifiersArray>(elements || []);
|
||||
array.pos = pos;
|
||||
array.end = end;
|
||||
export function createModifiersArray(elements?: Modifier[], location?: TextRange): ModifiersArray {
|
||||
let flags: NodeFlags;
|
||||
if (elements) {
|
||||
if (isModifiersArray(elements)) {
|
||||
return elements;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
for (const modifier of elements) {
|
||||
flags |= modifierToFlag(modifier.kind);
|
||||
}
|
||||
}
|
||||
else {
|
||||
elements = [];
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
const array = <ModifiersArray>elements;
|
||||
if (location) {
|
||||
array.pos = location.pos;
|
||||
array.end = location.end;
|
||||
}
|
||||
else {
|
||||
array.pos = -1;
|
||||
array.end = -1;
|
||||
}
|
||||
|
||||
array.arrayKind = ArrayKind.ModifiersArray;
|
||||
array.flags = 0;
|
||||
array.flags = flags;
|
||||
return array;
|
||||
}
|
||||
|
||||
function setModifiers(node: Node, modifiers: Modifier[]) {
|
||||
if (modifiers) {
|
||||
node.modifiers = createSynthesizedModifiersArray(modifiers);
|
||||
node.flags |= node.modifiers.flags;
|
||||
}
|
||||
else {
|
||||
node.modifiers = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
|
||||
const node = <SynthesizedNode>createNode(kind, /*location*/ undefined);
|
||||
node.startsOnNewLine = startsOnNewLine;
|
||||
@@ -40,11 +95,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createSynthesizedNodeArray<T extends Node>(elements?: T[]): NodeArray<T> {
|
||||
return createNodeArray(elements, /*pos*/ -1, /*end*/ -1);
|
||||
return createNodeArray(elements, /*location*/ undefined);
|
||||
}
|
||||
|
||||
export function createSynthesizedModifiersArray(elements?: Modifier[]): ModifiersArray {
|
||||
return createModifiersArray(elements, /*pos*/ -1, /*end*/ -1);
|
||||
return createModifiersArray(elements, /*location*/ undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,41 +148,28 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createReturn(expression?: Expression): ReturnStatement {
|
||||
const node = <ReturnStatement>createSynthesizedNode(SyntaxKind.ReturnStatement);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
// Literals
|
||||
|
||||
export function createLiteral(value: string): StringLiteral;
|
||||
export function createLiteral(value: number): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression;
|
||||
export function createLiteral<T extends PrimaryExpression>(value: string | number | boolean): T {
|
||||
if (typeof value === "number") {
|
||||
const node = <T & LiteralExpression>createNode(SyntaxKind.NumericLiteral);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <T>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
}
|
||||
else {
|
||||
const node = <T & StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
node.text = String(value);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export function createStatement(expression: Expression): ExpressionStatement {
|
||||
const node = <ExpressionStatement>createSynthesizedNode(SyntaxKind.ExpressionStatement);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVariableStatement(declarationList: VariableDeclarationList): VariableStatement {
|
||||
const node = <VariableStatement>createSynthesizedNode(SyntaxKind.VariableStatement);
|
||||
node.declarationList = declarationList;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVariableDeclarationList(declarations: VariableDeclaration[]): VariableDeclarationList {
|
||||
const node = <VariableDeclarationList>createSynthesizedNode(SyntaxKind.VariableDeclarationList);
|
||||
node.declarations = createNodeArray(declarations);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createBlock(statements: Statement[]): Block {
|
||||
const block = <Block>createSynthesizedNode(SyntaxKind.Block);
|
||||
block.statements = createNodeArray(statements);
|
||||
return block;
|
||||
}
|
||||
export function createVariableDeclaration(name: BindingPattern | Identifier, initializer?: Expression, location?: TextRange): VariableDeclaration {
|
||||
const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration, location);
|
||||
node.name = name;
|
||||
node.initializer = initializer;
|
||||
return node;
|
||||
}
|
||||
// Identifiers
|
||||
|
||||
export function createIdentifier(text: string): Identifier {
|
||||
const node = <Identifier>createNode(SyntaxKind.Identifier);
|
||||
@@ -151,33 +193,102 @@ namespace ts {
|
||||
return name;
|
||||
}
|
||||
|
||||
export function createLiteral(value: string): StringLiteral;
|
||||
export function createLiteral(value: number): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression;
|
||||
export function createLiteral<T extends PrimaryExpression>(value: string | number | boolean): T {
|
||||
if (typeof value === "number") {
|
||||
const node = <T & LiteralExpression>createNode(SyntaxKind.NumericLiteral);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <T>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
}
|
||||
else {
|
||||
const node = <T & StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
node.text = String(value);
|
||||
return node;
|
||||
}
|
||||
// Reserved words
|
||||
|
||||
export function createSuper() {
|
||||
const node = <PrimaryExpression>createNode(SyntaxKind.SuperKeyword);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVoid(expression: UnaryExpression) {
|
||||
const node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
export function createThis() {
|
||||
const node = <PrimaryExpression>createNode(SyntaxKind.ThisKeyword);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createNull() {
|
||||
const node = <PrimaryExpression>createNode(SyntaxKind.NullKeyword);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Names
|
||||
|
||||
export function createComputedPropertyName(expression: Expression, location?: TextRange) {
|
||||
const node = <ComputedPropertyName>createNode(SyntaxKind.ComputedPropertyName, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVoidZero() {
|
||||
return createVoid(createLiteral(0));
|
||||
// Type members
|
||||
|
||||
export function createMethod(modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
|
||||
const node = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createConstructor(parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
|
||||
const node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, location);
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createSynthesizedNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createGetAccessor(modifiers: Modifier[], name: string | PropertyName, body: Block, location?: TextRange) {
|
||||
const node = <GetAccessorDeclaration>createNode(SyntaxKind.GetAccessor, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray<ParameterDeclaration>();
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createSetAccessor(modifiers: Modifier[], name: string | PropertyName, parameter: ParameterDeclaration, body: Block, location?: TextRange) {
|
||||
const node = <SetAccessorDeclaration>createNode(SyntaxKind.SetAccessor, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray([parameter]);
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression) {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.dotDotDotToken = undefined;
|
||||
node.name = coerceBindingName(name);
|
||||
node.questionToken = undefined;
|
||||
node.type = undefined;
|
||||
node.initializer = initializer;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// Expression
|
||||
|
||||
export function createArrayLiteral(elements?: Expression[]) {
|
||||
const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
|
||||
node.elements = createNodeArray(elements);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createObjectLiteral(properties?: ObjectLiteralElement[]) {
|
||||
const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
|
||||
node.properties = createNodeArray(properties);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange) {
|
||||
@@ -195,13 +306,51 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression) {
|
||||
const node = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression);
|
||||
node.condition = condition;
|
||||
node.questionToken = createSynthesizedNode(SyntaxKind.QualifiedName);
|
||||
node.whenTrue = whenTrue;
|
||||
node.colonToken = createSynthesizedNode(SyntaxKind.ColonToken);
|
||||
node.whenFalse = whenFalse;
|
||||
export function createCall(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
|
||||
const node = <CallExpression>createNode(SyntaxKind.CallExpression, location);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.arguments = createNodeArray(argumentsArray);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createParen(expression: Expression, location?: TextRange) {
|
||||
const node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
|
||||
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location);
|
||||
node.modifiers = undefined;
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = coerceIdentifier(name);
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createArrowFunction(parameters: ParameterDeclaration[], body: Expression | Block, location?: TextRange) {
|
||||
const node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, location);
|
||||
node.modifiers = undefined;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
node.equalsGreaterThanToken = createNode(SyntaxKind.EqualsGreaterThanToken);
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createTypeOf(expression: Expression) {
|
||||
const node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
|
||||
node.expression = parenthesizeForUnary(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVoid(expression: Expression) {
|
||||
const node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
node.expression = parenthesizeForUnary(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -213,22 +362,194 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression) {
|
||||
const node = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression);
|
||||
node.condition = condition;
|
||||
node.questionToken = createSynthesizedNode(SyntaxKind.QualifiedName);
|
||||
node.whenTrue = whenTrue;
|
||||
node.colonToken = createSynthesizedNode(SyntaxKind.ColonToken);
|
||||
node.whenFalse = whenFalse;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createYield(expression: Expression, location?: TextRange) {
|
||||
const node = <YieldExpression>createNode(SyntaxKind.YieldExpression, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createSpread(expression: Expression) {
|
||||
const node = <SpreadElementExpression>createNode(SyntaxKind.SpreadElementExpression);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createClassExpression(name: Identifier, heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange) {
|
||||
const node = <ClassExpression>createNode(SyntaxKind.ClassExpression, location);
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.name = name;
|
||||
node.typeParameters = undefined;
|
||||
node.heritageClauses = createSynthesizedNodeArray(heritageClauses);
|
||||
node.members = createSynthesizedNodeArray(members);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createExpressionWithTypeArguments(expression: Expression, location?: TextRange) {
|
||||
const node = <ExpressionWithTypeArguments>createNode(SyntaxKind.ExpressionWithTypeArguments, location);
|
||||
node.typeArguments = undefined;
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Element
|
||||
|
||||
export function createBlock(statements: Statement[], location?: TextRange): Block {
|
||||
const block = <Block>createNode(SyntaxKind.Block, location);
|
||||
block.statements = createNodeArray(statements);
|
||||
return block;
|
||||
}
|
||||
|
||||
export function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList, location?: TextRange): VariableStatement {
|
||||
const node = <VariableStatement>createNode(SyntaxKind.VariableStatement, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.declarationList = declarationList;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVariableDeclarationList(declarations: VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableDeclarationList {
|
||||
const node = <VariableDeclarationList>createNode(SyntaxKind.VariableDeclarationList, location, flags);
|
||||
node.declarations = createNodeArray(declarations);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createLetDeclarationList(declarations: VariableDeclaration[], location?: TextRange) {
|
||||
return createVariableDeclarationList(declarations, location, NodeFlags.Let);
|
||||
}
|
||||
|
||||
export function createConstDeclarationList(declarations: VariableDeclaration[], location?: TextRange) {
|
||||
return createVariableDeclarationList(declarations, location, NodeFlags.Const);
|
||||
}
|
||||
|
||||
export function createVariableDeclaration(name: string | BindingPattern | Identifier, initializer?: Expression, location?: TextRange): VariableDeclaration {
|
||||
const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration, location);
|
||||
node.name = coerceBindingName(name);
|
||||
node.initializer = initializer;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createStatement(expression: Expression, location?: TextRange): ExpressionStatement {
|
||||
const node = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createReturn(expression?: Expression): ReturnStatement {
|
||||
const node = <ReturnStatement>createSynthesizedNode(SyntaxKind.ReturnStatement);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createFunctionDeclaration(modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
|
||||
const node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = coerceIdentifier(name);
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
node.body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createClassDeclaration(modifiers: Modifier[], name: Identifier, heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange) {
|
||||
const node = <ClassDeclaration>createNode(SyntaxKind.ClassDeclaration, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = name;
|
||||
node.typeParameters = undefined;
|
||||
node.heritageClauses = createSynthesizedNodeArray(heritageClauses);
|
||||
node.members = createSynthesizedNodeArray(members);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createExportDefault(expression: Expression) {
|
||||
const node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment);
|
||||
node.isExportEquals = false;
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createExportDeclaration(exportClause: NamedExports, moduleSpecifier?: Expression) {
|
||||
const node = <ExportDeclaration>createNode(SyntaxKind.ExportDeclaration);
|
||||
node.exportClause = exportClause;
|
||||
node.moduleSpecifier = moduleSpecifier;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createNamedExports(elements: ExportSpecifier[]) {
|
||||
const node = <NamedExports>createNode(SyntaxKind.NamedExports);
|
||||
node.elements = createNodeArray(elements);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier) {
|
||||
const node = <ExportSpecifier>createNode(SyntaxKind.ExportSpecifier);
|
||||
node.name = coerceIdentifier(name);
|
||||
node.propertyName = coerceIdentifier(propertyName);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Clauses
|
||||
|
||||
export function createHeritageClause(token: SyntaxKind, types: ExpressionWithTypeArguments[], location?: TextRange) {
|
||||
const node = <HeritageClause>createNode(SyntaxKind.HeritageClause, location);
|
||||
node.token = token;
|
||||
node.types = createSynthesizedNodeArray(types);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Compound nodes
|
||||
|
||||
export function createAssignment(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createBinary(left, SyntaxKind.EqualsToken, right, location);
|
||||
}
|
||||
|
||||
export function createLogicalAnd(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.AmpersandAmpersandToken, right);
|
||||
}
|
||||
|
||||
export function createLogicalOr(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.BarBarToken, right);
|
||||
}
|
||||
|
||||
export function createStrictEquality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.EqualsEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createStrictInequality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.ExclamationEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createComma(left: Expression, right: Expression) {
|
||||
return <Expression>createBinary(left, SyntaxKind.CommaToken, right);
|
||||
}
|
||||
|
||||
export function createCall(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
|
||||
const node = <CallExpression>createNode(SyntaxKind.CallExpression, location);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.arguments = createNodeArray(argumentsArray);
|
||||
export function createVoidZero() {
|
||||
return createVoid(createLiteral(0));
|
||||
}
|
||||
|
||||
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression {
|
||||
return isIdentifier(memberName)
|
||||
? createPropertyAccess(target, cloneNode(memberName), location)
|
||||
: createElementAccess(target, cloneNode(isComputedPropertyName(memberName) ? memberName.expression : memberName), location);
|
||||
}
|
||||
|
||||
export function createRestParameter(name: string | Identifier) {
|
||||
const node = createParameter(name, /*initializer*/ undefined);
|
||||
node.dotDotDotToken = createSynthesizedNode(SyntaxKind.DotDotDotToken);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -245,16 +566,232 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
export function parenthesizeExpression(expression: Expression) {
|
||||
const node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
// Helpers
|
||||
|
||||
export function createParamHelper(expression: Expression, parameterOffset: number) {
|
||||
return createCall(
|
||||
createIdentifier("__param"),
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
expression
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createMetadataHelper(metadataKey: string, metadataValue: Expression, defer?: boolean) {
|
||||
return createCall(
|
||||
createIdentifier("__metadata"),
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
defer
|
||||
? createArrowFunction([], metadataValue)
|
||||
: metadataValue
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) {
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions));
|
||||
argumentsArray.push(target);
|
||||
if (memberName) {
|
||||
argumentsArray.push(memberName);
|
||||
if (descriptor) {
|
||||
argumentsArray.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return createCall(createIdentifier("__decorate"), argumentsArray);
|
||||
}
|
||||
|
||||
export function createAwaiterHelper(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
return createCall(
|
||||
createIdentifier("__awaiter"),
|
||||
[
|
||||
createThis(),
|
||||
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
|
||||
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
|
||||
createFunctionExpression(
|
||||
createNode(SyntaxKind.AsteriskToken),
|
||||
/*name*/ undefined,
|
||||
[],
|
||||
body
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
function createObjectCreate(prototype: Expression) {
|
||||
return createCall(
|
||||
createPropertyAccess(createIdentifier("Object"), "create"),
|
||||
[prototype]
|
||||
);
|
||||
}
|
||||
|
||||
function createGeti(target: LeftHandSideExpression) {
|
||||
// name => super[name]
|
||||
return createArrowFunction(
|
||||
[createParameter("name")],
|
||||
createElementAccess(
|
||||
target,
|
||||
createIdentifier("name")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
function createSeti(target: LeftHandSideExpression) {
|
||||
// (name, value) => super[name] = value
|
||||
return createArrowFunction(
|
||||
[
|
||||
createParameter("name"),
|
||||
createParameter("value")
|
||||
],
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
target,
|
||||
createIdentifier("name")
|
||||
),
|
||||
createIdentifier("value")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function createAdvancedAsyncSuperHelper() {
|
||||
// const _super = (function (geti, seti) {
|
||||
// const cache = Object.create(null);
|
||||
// return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
// })(name => super[name], (name, value) => super[name] = value);
|
||||
|
||||
// const cache = Object.create(null);
|
||||
const createCache = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"cache",
|
||||
createObjectCreate(createNull())
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// get value() { return geti(name); }
|
||||
const getter = createGetAccessor(
|
||||
/*modifiers*/ undefined,
|
||||
"value",
|
||||
createBlock([
|
||||
createReturn(
|
||||
createCall(
|
||||
createIdentifier("geti"),
|
||||
[createIdentifier("name")]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// set value(v) { seti(name, v); }
|
||||
const setter = createSetAccessor(
|
||||
/*modifiers*/ undefined,
|
||||
"value",
|
||||
createParameter("v"),
|
||||
createBlock([
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("seti"),
|
||||
[
|
||||
createIdentifier("name"),
|
||||
createIdentifier("v")
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// return name => cache[name] || ...
|
||||
const getOrCreateAccessorsForName = createReturn(
|
||||
createArrowFunction(
|
||||
[createParameter("name")],
|
||||
createLogicalOr(
|
||||
createElementAccess(
|
||||
createIdentifier("cache"),
|
||||
createIdentifier("name")
|
||||
),
|
||||
createParen(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
createIdentifier("cache"),
|
||||
createIdentifier("name")
|
||||
),
|
||||
createObjectLiteral([
|
||||
getter,
|
||||
setter
|
||||
])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// const _super = (function (geti, seti) {
|
||||
// const cache = Object.create(null);
|
||||
// return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
// })(name => super[name], (name, value) => super[name] = value);
|
||||
return createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_super",
|
||||
createCall(
|
||||
createParen(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
[
|
||||
createParameter("geti"),
|
||||
createParameter("seti")
|
||||
],
|
||||
createBlock([
|
||||
createCache,
|
||||
getOrCreateAccessorsForName
|
||||
])
|
||||
)
|
||||
),
|
||||
[
|
||||
createGeti(createSuper()),
|
||||
createSeti(createSuper())
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export function createSimpleAsyncSuperHelper() {
|
||||
return createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_super",
|
||||
createGeti(createSuper())
|
||||
)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export function inlineExpressions(expressions: Expression[]) {
|
||||
return reduceLeft(expressions, createComma);
|
||||
}
|
||||
|
||||
export function createExpressionFromEntityName(node: EntityName | Expression): Expression {
|
||||
return isQualifiedName(node)
|
||||
? createPropertyAccess(
|
||||
createExpressionFromEntityName(node.left),
|
||||
cloneNode(node.right)
|
||||
)
|
||||
: cloneNode(node);
|
||||
}
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
function coerceIdentifier(value: string | Identifier) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
@@ -264,6 +801,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function coerceBindingName(value: string | BindingName) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function coercePropertyName(value: string | PropertyName) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function coerceExpression(value: string | number | boolean | Expression): Expression {
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
return createLiteral(value);
|
||||
@@ -291,7 +846,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
return needsParenthesesForBinary(operand, operator, side)
|
||||
? parenthesizeExpression(operand)
|
||||
? createParen(operand)
|
||||
: operand;
|
||||
}
|
||||
|
||||
@@ -343,6 +898,42 @@ namespace ts {
|
||||
return <LeftHandSideExpression>expr;
|
||||
}
|
||||
|
||||
return parenthesizeExpression(expr);
|
||||
return createParen(expr);
|
||||
}
|
||||
|
||||
function parenthesizeForUnary(operand: Expression) {
|
||||
if (isUnaryExpression(operand)) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
return createParen(operand);
|
||||
}
|
||||
|
||||
|
||||
export function startOnNewLine<T extends Node>(node: T): T {
|
||||
(<SynthesizedNode>node).startsOnNewLine = true;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setOriginalNode<T extends Node>(node: T, original: Node): T {
|
||||
node.original = original;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setTextRange<T extends TextRange>(node: T, location: TextRange): T {
|
||||
if (location) {
|
||||
node.pos = location.pos;
|
||||
node.end = location.end;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setNodeFlags<T extends Node>(node: T, flags: NodeFlags): T {
|
||||
node.flags = flags;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function getSynthesizedNode<T extends Node>(node: T): T {
|
||||
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,15 @@ function __export(m) {
|
||||
}
|
||||
})`;
|
||||
|
||||
const superHelper = `
|
||||
const _super = name => super[name];`;
|
||||
|
||||
const advancedSuperHelper = `
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);`;
|
||||
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const languageVersion = getLanguageVersion(compilerOptions);
|
||||
const moduleKind = getModuleKind(compilerOptions);
|
||||
@@ -122,8 +131,12 @@ function __export(m) {
|
||||
let startLexicalEnvironment: () => void;
|
||||
let endLexicalEnvironment: () => Statement[];
|
||||
let getNodeEmitFlags: (node: Node) => NodeEmitFlags;
|
||||
let isExpressionSubstitutionEnabled: (node: Node) => boolean;
|
||||
let isEmitNotificationEnabled: (node: Node) => boolean;
|
||||
let expressionSubstitution: (node: Expression) => Expression;
|
||||
let identifierSubstitution: (node: Identifier) => Identifier;
|
||||
let onBeforeEmitNode: (node: Node) => void;
|
||||
let onAfterEmitNode: (node: Node) => void;
|
||||
let isUniqueName: (name: string) => boolean;
|
||||
let temporaryVariables: string[] = [];
|
||||
let tempFlags: TempFlags;
|
||||
@@ -177,8 +190,12 @@ function __export(m) {
|
||||
startLexicalEnvironment = undefined;
|
||||
endLexicalEnvironment = undefined;
|
||||
getNodeEmitFlags = undefined;
|
||||
isExpressionSubstitutionEnabled = undefined;
|
||||
isEmitNotificationEnabled = undefined;
|
||||
expressionSubstitution = undefined;
|
||||
identifierSubstitution = undefined;
|
||||
onBeforeEmitNode = undefined;
|
||||
onAfterEmitNode = undefined;
|
||||
isUniqueName = undefined;
|
||||
temporaryVariables = undefined;
|
||||
tempFlags = 0;
|
||||
@@ -196,8 +213,12 @@ function __export(m) {
|
||||
startLexicalEnvironment = context.startLexicalEnvironment;
|
||||
endLexicalEnvironment = context.endLexicalEnvironment;
|
||||
getNodeEmitFlags = context.getNodeEmitFlags;
|
||||
isExpressionSubstitutionEnabled = context.isExpressionSubstitutionEnabled;
|
||||
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
|
||||
expressionSubstitution = context.expressionSubstitution;
|
||||
identifierSubstitution = context.identifierSubstitution;
|
||||
onBeforeEmitNode = context.onBeforeEmitNode;
|
||||
onAfterEmitNode = context.onAfterEmitNode;
|
||||
isUniqueName = context.isUniqueName;
|
||||
return printSourceFile;
|
||||
}
|
||||
@@ -213,6 +234,11 @@ function __export(m) {
|
||||
|
||||
function emit(node: Node) {
|
||||
if (node) {
|
||||
const adviseOnEmit = isEmitNotificationEnabled(node);
|
||||
if (adviseOnEmit && onBeforeEmitNode) {
|
||||
onBeforeEmitNode(node);
|
||||
}
|
||||
|
||||
const leadingComments = getLeadingCommentsToEmit(node);
|
||||
const trailingComments = getTrailingCommentsToEmit(node);
|
||||
emitLeadingComments(node, leadingComments);
|
||||
@@ -220,6 +246,10 @@ function __export(m) {
|
||||
emitWorker(node);
|
||||
emitEnd(node);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
|
||||
if (adviseOnEmit && onAfterEmitNode) {
|
||||
onAfterEmitNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +264,11 @@ function __export(m) {
|
||||
|
||||
// Identifiers
|
||||
case SyntaxKind.Identifier:
|
||||
return emitIdentifier(<Identifier>node, identifierSubstitution);
|
||||
if (tryEmitSubstitute(node, identifierSubstitution)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return emitIdentifier(<Identifier>node);
|
||||
|
||||
// Reserved words
|
||||
case SyntaxKind.ConstKeyword:
|
||||
@@ -486,6 +520,10 @@ function __export(m) {
|
||||
|
||||
function emitExpressionWorker(node: Node) {
|
||||
const kind = node.kind;
|
||||
if (isExpressionSubstitutionEnabled(node) && tryEmitSubstitute(node, expressionSubstitution)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
// Literals
|
||||
case SyntaxKind.NumericLiteral:
|
||||
@@ -496,16 +534,15 @@ function __export(m) {
|
||||
|
||||
// Identifiers
|
||||
case SyntaxKind.Identifier:
|
||||
return emitIdentifier(<Identifier>node, expressionSubstitution);
|
||||
return emitIdentifier(<Identifier>node);
|
||||
|
||||
// Reserved words
|
||||
case SyntaxKind.FalseKeyword:
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
return writeTokenNode(node);
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return emitThisKeyword(<PrimaryExpression>node);
|
||||
return writeTokenNode(node);
|
||||
|
||||
// Expressions
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
@@ -597,11 +634,8 @@ function __export(m) {
|
||||
// Identifiers
|
||||
//
|
||||
|
||||
function emitIdentifier(node: Identifier, substitution: (node: Node) => Node) {
|
||||
if (tryEmitSubstitute(node, substitution)) {
|
||||
return;
|
||||
}
|
||||
else if (node.text === undefined) {
|
||||
function emitIdentifier(node: Identifier) {
|
||||
if (node.text === undefined) {
|
||||
// Emit a temporary variable name for this node.
|
||||
const nodeId = getOriginalNodeId(node);
|
||||
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(tempKindToFlags(node.tempKind)));
|
||||
@@ -620,15 +654,6 @@ function __export(m) {
|
||||
}
|
||||
}
|
||||
|
||||
function emitThisKeyword(node: PrimaryExpression) {
|
||||
if (tryEmitSubstitute(node, expressionSubstitution)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
writeTokenNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Names
|
||||
//
|
||||
@@ -1051,19 +1076,11 @@ function __export(m) {
|
||||
}
|
||||
|
||||
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
|
||||
if (tryEmitSubstitute(node, expressionSubstitution)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitExpression(node.operand);
|
||||
writeToken(node.operator);
|
||||
}
|
||||
|
||||
function emitBinaryExpression(node: BinaryExpression) {
|
||||
if (tryEmitSubstitute(node, expressionSubstitution)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken;
|
||||
const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken);
|
||||
const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right);
|
||||
@@ -1390,9 +1407,12 @@ function __export(m) {
|
||||
|
||||
function emitBlockFunctionBody(parentNode: Node, body: Block) {
|
||||
// Emit all the prologue directives (like "use strict").
|
||||
increaseIndent();
|
||||
const statements = body.statements;
|
||||
const statementOffset = emitPrologueDirectives(statements, /*startWithNewLine*/ true, /*indented*/ true);
|
||||
const statementOffset = emitPrologueDirectives(statements, /*startWithNewLine*/ true);
|
||||
const helpersEmitted = emitHelpers(body);
|
||||
decreaseIndent();
|
||||
|
||||
if (statementOffset === 0 && !helpersEmitted && shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)) {
|
||||
emitList(body, statements, ListFormat.SingleLineFunctionBodyStatements);
|
||||
}
|
||||
@@ -1688,6 +1708,7 @@ function __export(m) {
|
||||
|
||||
function emitHeritageClause(node: HeritageClause) {
|
||||
emitStart(node);
|
||||
write(" ");
|
||||
writeToken(node.token);
|
||||
write(" ");
|
||||
emitList(node, node.types, ListFormat.HeritageClauseTypes);
|
||||
@@ -1783,8 +1804,7 @@ function __export(m) {
|
||||
}
|
||||
}
|
||||
|
||||
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, indented?: boolean) {
|
||||
increaseIndentIf(indented);
|
||||
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean) {
|
||||
for (let i = 0; i < statements.length; i++) {
|
||||
if (isPrologueDirective(statements[i])) {
|
||||
if (startWithNewLine || i > 0) {
|
||||
@@ -1794,24 +1814,32 @@ function __export(m) {
|
||||
}
|
||||
else {
|
||||
// return index of the first non prologue directive
|
||||
decreaseIndentIf(indented);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
decreaseIndentIf(indented);
|
||||
return statements.length;
|
||||
}
|
||||
|
||||
function emitHelpers(node: Node) {
|
||||
const emitFlags = getNodeEmitFlags(node);
|
||||
let helpersEmitted = false;
|
||||
if (emitFlags & NodeEmitFlags.EmitHelpers) {
|
||||
if (emitFlags & NodeEmitFlags.EmitEmitHelpers) {
|
||||
helpersEmitted = emitEmitHelpers(currentSourceFile);
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.EmitExportStar) {
|
||||
emitExportStarHelper();
|
||||
writeLines(exportStarHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.EmitSuperHelper) {
|
||||
writeLines(superHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.EmitAdvancedSuperHelper) {
|
||||
writeLines(advancedSuperHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
@@ -1861,10 +1889,6 @@ function __export(m) {
|
||||
return helpersEmitted;
|
||||
}
|
||||
|
||||
function emitExportStarHelper() {
|
||||
writeLines(exportStarHelper);
|
||||
}
|
||||
|
||||
function writeLines(text: string): void {
|
||||
const lines = text.split(/\r\n|\r|\n/g);
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace ts {
|
||||
const nodeEmitFlags: NodeEmitFlags[] = [];
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledExpressionSubstitutions = new Array<boolean>(SyntaxKind.Count);
|
||||
const enabledEmitNotifications = new Array<boolean>(SyntaxKind.Count);
|
||||
|
||||
let lexicalEnvironmentStackOffset = 0;
|
||||
let hoistedVariableDeclarations: VariableDeclaration[];
|
||||
let hoistedFunctionDeclarations: FunctionDeclaration[];
|
||||
@@ -75,7 +78,11 @@ namespace ts {
|
||||
hoistVariableDeclaration,
|
||||
hoistFunctionDeclaration,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment
|
||||
endLexicalEnvironment,
|
||||
enableExpressionSubstitution,
|
||||
isExpressionSubstitutionEnabled,
|
||||
enableEmitNotification,
|
||||
isEmitNotificationEnabled,
|
||||
};
|
||||
|
||||
// Chain together and initialize each transformer.
|
||||
@@ -100,6 +107,23 @@ namespace ts {
|
||||
return visited;
|
||||
}
|
||||
|
||||
function enableExpressionSubstitution(kind: SyntaxKind) {
|
||||
enabledExpressionSubstitutions[kind] = true;
|
||||
}
|
||||
|
||||
function isExpressionSubstitutionEnabled(node: Node) {
|
||||
return enabledExpressionSubstitutions[node.kind];
|
||||
}
|
||||
|
||||
function enableEmitNotification(kind: SyntaxKind) {
|
||||
enabledEmitNotifications[kind] = true;
|
||||
}
|
||||
|
||||
function isEmitNotificationEnabled(node: Node) {
|
||||
return enabledEmitNotifications[node.kind]
|
||||
|| (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets flags that control emit behavior of a node.
|
||||
*/
|
||||
@@ -207,7 +231,7 @@ namespace ts {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return generateNameForClassExpression();
|
||||
default:
|
||||
return createTempVariable(TempVariableKind.Auto);
|
||||
return createTempVariable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +313,7 @@ namespace ts {
|
||||
if (hoistedVariableDeclarations) {
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(hoistedVariableDeclarations)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -10,8 +10,14 @@ namespace ts {
|
||||
* @param needsValue Indicates whether the value from the right-hand-side of the
|
||||
* destructuring assignment is needed as part of a larger expression.
|
||||
* @param recordTempVariable A callback used to record new temporary variables.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenDestructuringAssignment(node: BinaryExpression, needsValue: boolean, recordTempVariable: (node: Identifier) => void) {
|
||||
export function flattenDestructuringAssignment(
|
||||
node: BinaryExpression,
|
||||
needsValue: boolean,
|
||||
recordTempVariable: (node: Identifier) => void,
|
||||
visitor?: (node: Node) => Node) {
|
||||
|
||||
let location: TextRange = node;
|
||||
let value = node.right;
|
||||
if (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
@@ -31,7 +37,7 @@ namespace ts {
|
||||
location = node.right;
|
||||
}
|
||||
|
||||
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment);
|
||||
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
if (needsValue) {
|
||||
expressions.push(value);
|
||||
@@ -64,11 +70,12 @@ namespace ts {
|
||||
*
|
||||
* @param node The ParameterDeclaration to flatten.
|
||||
* @param value The rhs value for the binding pattern.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenParameterDestructuring(node: ParameterDeclaration, value: Expression) {
|
||||
export function flattenParameterDestructuring(node: ParameterDeclaration, value: Expression, visitor?: (node: Node) => Node) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment);
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
return declarations;
|
||||
|
||||
@@ -94,11 +101,12 @@ namespace ts {
|
||||
*
|
||||
* @param node The VariableDeclaration to flatten.
|
||||
* @param value An optional rhs value for the binding pattern.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenVariableDestructuring(node: VariableDeclaration, value?: Expression) {
|
||||
export function flattenVariableDestructuring(node: VariableDeclaration, value?: Expression, visitor?: (node: Node) => Node) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment);
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
return declarations;
|
||||
|
||||
@@ -129,8 +137,15 @@ namespace ts {
|
||||
*
|
||||
* @param node The VariableDeclaration to flatten.
|
||||
* @param recordTempVariable A callback used to record new temporary variables.
|
||||
* @param nameSubstitution An optional callback used to substitute binding names.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenVariableDestructuringToExpression(node: VariableDeclaration, recordTempVariable: (name: Identifier) => void) {
|
||||
export function flattenVariableDestructuringToExpression(
|
||||
node: VariableDeclaration,
|
||||
recordTempVariable: (name: Identifier) => void,
|
||||
nameSubstitution?: (name: Identifier) => Expression,
|
||||
visitor?: (node: Node) => Node) {
|
||||
|
||||
const pendingAssignments: Expression[] = [];
|
||||
|
||||
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment);
|
||||
@@ -140,6 +155,18 @@ namespace ts {
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
const left = nameSubstitution && nameSubstitution(name) || name;
|
||||
emitPendingAssignment(left, value, location, original);
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable();
|
||||
recordTempVariable(name);
|
||||
emitPendingAssignment(name, value, location, /*original*/ undefined);
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitPendingAssignment(name: Expression, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
if (isSimpleExpression(value)) {
|
||||
(<SynthesizedNode>expression).disableSourceMap = true;
|
||||
@@ -147,13 +174,7 @@ namespace ts {
|
||||
|
||||
expression.original = original;
|
||||
pendingAssignments.push(expression);
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable();
|
||||
recordTempVariable(name);
|
||||
emitAssignment(name, value, location, /*original*/ undefined);
|
||||
return name;
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +183,12 @@ namespace ts {
|
||||
value: Expression,
|
||||
location: TextRange,
|
||||
emitAssignment: (name: Identifier, value: Expression, location: TextRange, original: Node) => void,
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier) {
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
|
||||
visitor?: (node: Node) => Node) {
|
||||
if (value && visitor) {
|
||||
value = visitNode(value, visitor, isExpression);
|
||||
}
|
||||
|
||||
if (isBinaryExpression(root)) {
|
||||
emitDestructuringAssignment(root.left, value, location)
|
||||
}
|
||||
@@ -174,14 +200,22 @@ namespace ts {
|
||||
// When emitting target = value use source map node to highlight, including any temporary assignments needed for this
|
||||
let target: Expression;
|
||||
if (isShortHandPropertyAssignment(bindingTarget)) {
|
||||
if (bindingTarget.objectAssignmentInitializer) {
|
||||
value = createDefaultValueCheck(value, bindingTarget.objectAssignmentInitializer, location);
|
||||
const initializer = visitor
|
||||
? visitNode(bindingTarget.objectAssignmentInitializer, visitor, isExpression)
|
||||
: bindingTarget.objectAssignmentInitializer;
|
||||
|
||||
if (initializer) {
|
||||
value = createDefaultValueCheck(value, initializer, location);
|
||||
}
|
||||
|
||||
target = bindingTarget.name;
|
||||
}
|
||||
else if (isBinaryExpression(bindingTarget) && bindingTarget.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
value = createDefaultValueCheck(value, bindingTarget.right, location);
|
||||
const initializer = visitor
|
||||
? visitNode(bindingTarget.right, visitor, isExpression)
|
||||
: bindingTarget.right;
|
||||
|
||||
value = createDefaultValueCheck(value, initializer, location);
|
||||
target = bindingTarget.left;
|
||||
}
|
||||
else {
|
||||
@@ -244,9 +278,10 @@ namespace ts {
|
||||
|
||||
function emitBindingElement(target: BindingElement, value: Expression) {
|
||||
// Any temporary assignments needed to emit target = value should point to target
|
||||
if (target.initializer) {
|
||||
const initializer = visitor ? visitNode(target.initializer, visitor, isExpression) : target.initializer;
|
||||
if (initializer) {
|
||||
// Combine value and initializer
|
||||
value = value ? createDefaultValueCheck(value, target.initializer, target) : target.initializer;
|
||||
value = value ? createDefaultValueCheck(value, initializer, target) : initializer;
|
||||
}
|
||||
else if (!value) {
|
||||
// Use 'void 0' in absence of value and initializer
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1301,7 +1301,7 @@ namespace ts {
|
||||
export interface EnumMember extends Declaration {
|
||||
// This does include ComputedPropertyName, but the parser will give an error
|
||||
// if it parses a ComputedPropertyName in an EnumMember
|
||||
name: DeclarationName;
|
||||
name: PropertyName;
|
||||
initializer?: Expression;
|
||||
}
|
||||
|
||||
@@ -2792,12 +2792,15 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export const enum NodeEmitFlags {
|
||||
EmitHelpers = 1 << 0, // Any emit helpers should be written to this node.
|
||||
EmitExportStar = 1 << 1, // The export * helper should be written to this node.
|
||||
UMDDefine = 1 << 2, // This node should be replaced with the UMD define helper.
|
||||
NoLexicalEnvironment = 1 << 3, // A new LexicalEnvironment should *not* be introduced when emitting this node.
|
||||
SingleLine = 1 << 4, // The contents of this node should be emit on a single line.
|
||||
MultiLine = 1 << 5, // The contents of this node should be emit on multiple lines.
|
||||
EmitEmitHelpers = 1 << 0, // Any emit helpers should be written to this node.
|
||||
EmitExportStar = 1 << 1, // The export * helper should be written to this node.
|
||||
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
|
||||
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
|
||||
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
|
||||
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node.
|
||||
SingleLine = 1 << 6, // The contents of this node should be emit on a single line.
|
||||
MultiLine = 1 << 7, // The contents of this node should be emit on multiple lines.
|
||||
AdviseOnEmitNode = 1 << 8, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
@@ -2821,8 +2824,14 @@ namespace ts {
|
||||
getGeneratedNameForNode(node: Node): Identifier;
|
||||
nodeHasGeneratedName(node: Node): boolean;
|
||||
makeUniqueName(baseName: string): Identifier;
|
||||
enableExpressionSubstitution(kind: SyntaxKind): void;
|
||||
isExpressionSubstitutionEnabled(node: Node): boolean;
|
||||
identifierSubstitution?: (node: Identifier) => Identifier;
|
||||
expressionSubstitution?: (node: Expression) => Expression;
|
||||
enableEmitNotification(kind: SyntaxKind): void;
|
||||
isEmitNotificationEnabled(node: Node): boolean;
|
||||
onBeforeEmitNode?: (node: Node) => void;
|
||||
onAfterEmitNode?: (node: Node) => void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -1018,6 +1018,20 @@ namespace ts {
|
||||
&& nodeCanBeDecorated(node);
|
||||
}
|
||||
|
||||
export function nodeOrChildIsDecorated(node: Node): boolean {
|
||||
return nodeIsDecorated(node) || childIsDecorated(node);
|
||||
}
|
||||
|
||||
export function childIsDecorated(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
|
||||
}
|
||||
}
|
||||
|
||||
export function isPartOfExpression(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SuperKeyword:
|
||||
@@ -2252,7 +2266,14 @@ namespace ts {
|
||||
return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
|
||||
}
|
||||
|
||||
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration) {
|
||||
export interface AllAccessorDeclarations {
|
||||
firstAccessor: AccessorDeclaration;
|
||||
secondAccessor: AccessorDeclaration;
|
||||
getAccessor: AccessorDeclaration;
|
||||
setAccessor: AccessorDeclaration;
|
||||
}
|
||||
|
||||
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration): AllAccessorDeclarations {
|
||||
let firstAccessor: AccessorDeclaration;
|
||||
let secondAccessor: AccessorDeclaration;
|
||||
let getAccessor: AccessorDeclaration;
|
||||
@@ -2816,7 +2837,6 @@ namespace ts {
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor
|
||||
|| kind === SyntaxKind.MethodSignature
|
||||
|| kind === SyntaxKind.IndexSignature;
|
||||
}
|
||||
|
||||
@@ -2849,6 +2869,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.BinaryExpression;
|
||||
}
|
||||
|
||||
export function isConditionalExpression(node: Node): node is ConditionalExpression {
|
||||
return node.kind === SyntaxKind.ConditionalExpression;
|
||||
}
|
||||
|
||||
export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
|
||||
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
|
||||
}
|
||||
@@ -3241,8 +3265,12 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.NodeArrayNode;
|
||||
}
|
||||
|
||||
export function isModifiersArray(array: NodeArray<Node>): array is ModifiersArray {
|
||||
return array.arrayKind === ArrayKind.ModifiersArray;
|
||||
export function isNodeArray<T extends Node>(array: T[]): array is NodeArray<T> {
|
||||
return (<NodeArray<T>>array).arrayKind === ArrayKind.ModifiersArray;
|
||||
}
|
||||
|
||||
export function isModifiersArray(array: Modifier[]): array is ModifiersArray {
|
||||
return (<ModifiersArray>array).arrayKind === ArrayKind.ModifiersArray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export type OneOrMore<T extends Node> = T | NodeArrayNode<T>;
|
||||
|
||||
/**
|
||||
* Describes an edge of a Node, used when traversing a syntax tree.
|
||||
*/
|
||||
@@ -472,7 +474,7 @@ namespace ts {
|
||||
* @param lift A callback to execute to lift a NodeArrayNode into a valid Node.
|
||||
* @param optional A value indicating whether the Node is optional.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => Node, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T, optional?: boolean): T {
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => Node, test?: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -490,6 +492,7 @@ namespace ts {
|
||||
|
||||
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.");
|
||||
aggregateTransformFlags(visited);
|
||||
visited.original = node;
|
||||
return <T>visited;
|
||||
}
|
||||
|
||||
@@ -500,54 +503,55 @@ namespace ts {
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
*/
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test?: (node: Node) => boolean): TArray {
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): TArray;
|
||||
export function visitNodes<T extends Node, U extends Node>(nodes: T[], visitor: (node: T) => U): NodeArray<U>;
|
||||
export function visitNodes<T extends Node>(nodes: T[], visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): TArray {
|
||||
if (nodes === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let updated: NodeArray<T> | ModifiersArray;
|
||||
for (let i = 0, len = nodes.length; i < len; i++) {
|
||||
const node = nodes[i];
|
||||
const len = nodes.length;
|
||||
start = start !== undefined ? Math.max(start, 0) : 0;
|
||||
count = count !== undefined ? Math.min(count, len - start) : len - start;
|
||||
|
||||
let updated: T[];
|
||||
if (start > 0 || count < len) {
|
||||
updated = [];
|
||||
}
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const node = nodes[i + start];
|
||||
if (node === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const visited = visitor(node);
|
||||
const visited = <OneOrMore<T>>visitor(node);
|
||||
if (updated !== undefined || visited === undefined || visited !== node) {
|
||||
if (updated === undefined) {
|
||||
updated = isModifiersArray(nodes)
|
||||
? createModifiersArray(nodes.slice(0, i), nodes.pos, nodes.end)
|
||||
: createNodeArray<T>(nodes.slice(0, i), nodes.pos, nodes.end);
|
||||
updated = nodes.slice(0, i);
|
||||
}
|
||||
|
||||
if (visited === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isNodeArrayNode<T>(visited)) {
|
||||
spreadNodeArrayNode(visited, updated, test);
|
||||
if (visited !== node) {
|
||||
aggregateTransformFlags(visited);
|
||||
visited.original = node;
|
||||
}
|
||||
else if (visited !== undefined) {
|
||||
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.");
|
||||
if (visited !== node) {
|
||||
aggregateTransformFlags(visited);
|
||||
}
|
||||
|
||||
updated.push(<T>visited);
|
||||
}
|
||||
addNode(updated, visited, test);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated && isModifiersArray(updated)) {
|
||||
let flags: NodeFlags = 0;
|
||||
for (const node of updated) {
|
||||
flags |= modifierToFlag(node.kind);
|
||||
}
|
||||
|
||||
updated.flags = flags;
|
||||
if (updated) {
|
||||
return <TArray>(isModifiersArray(nodes)
|
||||
? createModifiersArray(updated, /*location*/ nodes)
|
||||
: createNodeArray(updated, /*location*/ nodes));
|
||||
}
|
||||
|
||||
return <TArray>updated || nodes;
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,6 +610,7 @@ namespace ts {
|
||||
|
||||
if (updated !== node) {
|
||||
aggregateTransformFlags(updated);
|
||||
updated.original = node;
|
||||
}
|
||||
|
||||
return updated;
|
||||
@@ -621,24 +626,40 @@ namespace ts {
|
||||
function visitEdge(edge: NodeEdge, value: Node | NodeArray<Node>, visitor: (node: Node) => Node) {
|
||||
return isArray(value)
|
||||
? visitNodes(<NodeArray<Node>>value, visitor, edge.test)
|
||||
: visitNode(<Node>value, visitor, edge.test, edge.lift, edge.optional);
|
||||
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spreads a NodeArrayNode into a NodeArray.
|
||||
* Appends a node to an array.
|
||||
*
|
||||
* @param source The source NodeArrayNode.
|
||||
* @param dest The destination NodeArray.
|
||||
* @param to The destination array.
|
||||
* @param from The source Node or NodeArrayNode.
|
||||
* @param test The node test used to validate each node.
|
||||
*/
|
||||
function spreadNodeArrayNode<T extends Node>(source: NodeArrayNode<T>, dest: NodeArray<T>, test: (node: Node) => boolean) {
|
||||
for (const element of source.nodes) {
|
||||
if (element === undefined) {
|
||||
continue;
|
||||
export function addNode<T extends Node>(to: T[], from: OneOrMore<T>, test?: (node: Node) => boolean) {
|
||||
if (to && from) {
|
||||
if (isNodeArrayNode(from)) {
|
||||
addNodes(to, from.nodes, test);
|
||||
}
|
||||
else {
|
||||
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
|
||||
to.push(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.assert(test === undefined || test(element), "Wrong node type after visit.");
|
||||
dest.push(element);
|
||||
/**
|
||||
* Appends an array of nodes to an array.
|
||||
*
|
||||
* @param to The destination NodeArray.
|
||||
* @param from The source array of Node or NodeArrayNode.
|
||||
* @param test The node test used to validate each node.
|
||||
*/
|
||||
export function addNodes<T extends Node>(to: T[], from: OneOrMore<T>[], test?: (node: Node) => boolean) {
|
||||
if (to && from) {
|
||||
for (const node of from) {
|
||||
addNode(to, node, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,14 +716,31 @@ namespace ts {
|
||||
*/
|
||||
function mergeFunctionLikeLexicalEnvironment(node: FunctionLikeDeclaration, declarations: Statement[]) {
|
||||
Debug.assert(node.body !== undefined);
|
||||
if (node.body.kind === SyntaxKind.Block) {
|
||||
node.body = <Block>mergeLexicalEnvironment(node.body, declarations, /*nodeIsMutable*/ false);
|
||||
node.body = mergeConciseBodyLexicalEnvironment(node.body, declarations);
|
||||
}
|
||||
|
||||
export function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[], nodeIsMutable?: boolean): FunctionBody {
|
||||
if (declarations && declarations.length > 0) {
|
||||
return <Block>mergeLexicalEnvironment(body, declarations, nodeIsMutable);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
export function mergeConciseBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[], nodeIsMutable?: boolean): ConciseBody {
|
||||
if (declarations && declarations.length > 0) {
|
||||
if (isBlock(body)) {
|
||||
return <Block>mergeLexicalEnvironment(body, declarations, nodeIsMutable);
|
||||
}
|
||||
else {
|
||||
return createBlock([
|
||||
createReturn(body),
|
||||
...declarations
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
node.body = createBlock([
|
||||
createReturn(<Expression>node.body),
|
||||
...declarations
|
||||
]);
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,7 +755,7 @@ namespace ts {
|
||||
* Merge generated declarations of a lexical environment into a NodeArray of Statement.
|
||||
*/
|
||||
function mergeStatements(statements: NodeArray<Statement>, declarations: Statement[]) {
|
||||
return createNodeArray(statements.concat(declarations), statements.pos, statements.end);
|
||||
return createNodeArray(concatenate(statements, declarations), /*location*/ statements);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user