From 74ac4c5b1c4ab65637996319d84955fc096a53e0 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 28 Oct 2015 13:33:03 -0700 Subject: [PATCH] Fixed bugs in emit for more consistent output and missing hints for transformations. --- scripts/processTypes/processTypes.ts | 18 - src/compiler/binder.ts | 276 +++-- src/compiler/checker.ts | 4 +- src/compiler/core.ts | 59 +- src/compiler/factory.generated.ts | 1339 +--------------------- src/compiler/factory.ts | 47 +- src/compiler/printer.ts | 825 +++++++------ src/compiler/transform.ts | 490 ++++---- src/compiler/transforms/destructuring.ts | 21 +- src/compiler/transforms/es6.ts | 294 ++++- src/compiler/transforms/module/module.ts | 1 - src/compiler/transforms/module/system.ts | 15 +- src/compiler/transforms/ts.ts | 157 ++- src/compiler/types.ts | 300 ++--- src/compiler/utilities.ts | 52 +- 15 files changed, 1580 insertions(+), 2318 deletions(-) diff --git a/scripts/processTypes/processTypes.ts b/scripts/processTypes/processTypes.ts index 814ed96612e..470154a631e 100644 --- a/scripts/processTypes/processTypes.ts +++ b/scripts/processTypes/processTypes.ts @@ -70,24 +70,6 @@ namespace ts {${each(discovery.createableNodes, syntaxNode => ` } return false; }`)} - export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode; - export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node { - if (node) { - let clone: Node; - switch (node.kind) {${each(discovery.createableNodes, syntaxNode => ` - case SyntaxKind.${syntaxNode.kindName}: - clone = ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => - `(<${syntaxNode.typeName}>node).${member.propertyName}, ` - )}location, flags); - break;`)} - } - if (clone) { - clone.original = node; - return clone; - } - } - return node; - } export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node { if (node) { switch (node.kind) {${each(discovery.updateableNodes, syntaxNode => ` diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a55efc8ff2d..5c5063aa841 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1130,6 +1130,10 @@ namespace ts { export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) { Debug.assert((subtreeFlags & TransformFlags.NodeExcludes) == 0, "Subtree includes a `ThisNode...` flag."); + if (node.flags & NodeFlags.Ambient) { + return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; + } + // Mark transformations needed for each node let transformFlags: TransformFlags; let excludeFlags: TransformFlags; @@ -1145,8 +1149,10 @@ namespace ts { case SyntaxKind.AwaitExpression: case SyntaxKind.EnumDeclaration: case SyntaxKind.EnumMember: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: // These nodes are TypeScript syntax. - transformFlags |= TransformFlags.ThisNodeIsTypeScript; + transformFlags |= TransformFlags.TypeScript; break; case SyntaxKind.JsxElement: @@ -1169,23 +1175,57 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.ForOfStatement: - case SyntaxKind.ComputedPropertyName: case SyntaxKind.YieldExpression: // These nodes are ES6 syntax. transformFlags |= TransformFlags.ThisNodeIsES6; break; + + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.TypePredicate: + case SyntaxKind.TypeReference: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeLiteral: + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + // Types and signatures are TypeScript syntax, and exclude all other facts. + excludeFlags = TransformFlags.TypeExcludes; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + case SyntaxKind.ComputedPropertyName: // Even though computed property names are ES6, we don't treat them as such. // This is so that they can flow through PropertyName transforms unaffected. // Instead, we mark the container as ES6, so that it can properly handle the transform. - transformFlags |= TransformFlags.ContainerIsES6; + transformFlags |= TransformFlags.ContainsComputedPropertyName; break; case SyntaxKind.SpreadElementExpression: + // This node is ES6 syntax, but is handled by a containing node. + transformFlags |= TransformFlags.ContainsSpreadElementExpression; + break; + case SyntaxKind.SuperKeyword: - // These nodes are ES6 syntax, and mark their immediate containers as ES6. - transformFlags |= TransformFlags.ThisNodeIsES6 | TransformFlags.ContainerIsES6; + // This node is ES6 syntax. + transformFlags |= TransformFlags.ThisNodeIsES6; break; case SyntaxKind.ThisKeyword: @@ -1193,11 +1233,6 @@ namespace ts { transformFlags |= TransformFlags.ContainsLexicalThis; break; - // case SyntaxKind.BreakStatement: - // case SyntaxKind.ContinueStatement: - // case SyntaxKind.ReturnStatement: - // return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsCompletionStatement; - case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: // These nodes are ES6 syntax. @@ -1205,29 +1240,39 @@ namespace ts { break; case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - // If the subtree has marked the container as ES6, then these nodes are ES6. - if (subtreeFlags & TransformFlags.ContainerIsES6) { - excludeFlags = TransformFlags.ContainerIsES6; - transformFlags |= TransformFlags.ES6; + excludeFlags = TransformFlags.ObjectLiteralExpressionExcludes; + if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= TransformFlags.ThisNodeIsES6; } - break; - case SyntaxKind.PropertyAssignment: - // If the name of the assignment is a ComputedPropertyName, we need to mark the container - // as ES6 so that it is picked up by the transformer. - if (isComputedPropertyName((node).name)) { - transformFlags |= TransformFlags.ContainerIsES6; + case SyntaxKind.CallExpression: + excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExpressionExcludes; + if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression || + (node).expression.kind === SyntaxKind.SuperKeyword || + (node).expression.kind === SyntaxKind.PropertyAccessExpression && + ((node).expression).expression.kind === SyntaxKind.SuperKeyword) { + // If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= TransformFlags.ThisNodeIsES6; + } + break; + + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.NewExpression: + excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExpressionExcludes; + if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) { + // If the this node contains a SpreadElementExpression, then it is an ES6 + // node. + transformFlags |= TransformFlags.ThisNodeIsES6; } break; case SyntaxKind.Decorator: // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - transformFlags |= TransformFlags.ContainerIsTypeScript; + transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainsDecorator; break; case SyntaxKind.ModuleDeclaration: @@ -1236,10 +1281,14 @@ namespace ts { transformFlags |= TransformFlags.ThisNodeIsTypeScript; break; - // case SyntaxKind.ArrayLiteralExpression: - // case SyntaxKind.CallExpression: - // return (node.transformFlags = subtreeFlags) - // & ~(node.excludeTransformFlags = TransformFlags.CallOrArrayLiteralExcludes); + case SyntaxKind.ParenthesizedExpression: + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (!nodeIsSynthesized(node) && (isTypeAssertionExpression((node).expression) || isAsExpression((node).expression))) { + transformFlags = TransformFlags.ThisNodeIsTypeScript; + } + break; case SyntaxKind.ExpressionStatement: if (node.flags & NodeFlags.Generated) { @@ -1252,37 +1301,14 @@ namespace ts { break; case SyntaxKind.BinaryExpression: - // Destructuring assignments are ES6 syntax. if (isDestructuringAssignment(node)) { + // Destructuring assignments are ES6 syntax. transformFlags |= TransformFlags.ThisNodeIsES6; } - - break; - - case SyntaxKind.AnyKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.TypeParameter: - case SyntaxKind.TypeReference: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.PropertySignature: - // Types and signatures are TypeScript syntax, and exclude all other facts. - excludeFlags = TransformFlags.TypeExcludes; - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - break; - - case SyntaxKind.PropertyDeclaration: - // Property declarations are TypeScript syntax. - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - - // If the declration has an initializer, we must mark the container as being TypeScript syntax. - if ((node).initializer) { - transformFlags |= TransformFlags.ContainerIsTypeScript; + else if ((node).operatorToken.kind === SyntaxKind.AsteriskAsteriskToken || + (node).operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) { + // Exponentiation is ES7 syntax. + transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; @@ -1295,17 +1321,14 @@ namespace ts { // If a parameter has an accessibility modifier, then it is TypeScript syntax. if ((node).flags & NodeFlags.AccessibilityModifier) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainerIsTypeScript; + transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainsParameterPropertyAssignment; } - // If a parameter has a dotDotDot token, then it is ES6 syntax. - if ((node).dotDotDotToken) { - transformFlags |= TransformFlags.ThisNodeIsES6; - } - - // If a parameter has an initializer or a binding pattern, then it is ES6 syntax and its container - // must emit default value assignments or parameter destructuring downlevel. - if ((node).initializer || isBindingPattern((node).name)) { + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if ((node).initializer || + isBindingPattern((node).name) || + (node).dotDotDotToken) { transformFlags |= TransformFlags.ThisNodeIsES6 | TransformFlags.ContainsDefaultValueAssignments; } @@ -1321,9 +1344,8 @@ namespace ts { transformFlags |= TransformFlags.ContainsCapturedLexicalThis; } - // If an ArrowFunction is marked async, or its subtree has marked the container as being - // TypeScript syntax, then the node is TypeScript Syntax. - if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + // An async arrow function is TypeScript syntax. + if (node.flags & NodeFlags.Async) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } @@ -1335,13 +1357,12 @@ namespace ts { // If a FunctionExpression contains an asterisk token, or its subtree has marked the container // as needing to capture the lexical this, then this node is ES6 syntax. - if ((node).asteriskToken || transformFlags & TransformFlags.ContainsCapturedLexicalThis) { + if ((node).asteriskToken || transformFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)) { transformFlags |= TransformFlags.ThisNodeIsES6; } - // If a FunctionExpression is async, or its subtree has marked the container - // as TypeScript, then this node is TypeScript syntax. - if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + // An async function expression is TypeScript syntax. + if (node.flags & NodeFlags.Async) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } @@ -1357,29 +1378,32 @@ namespace ts { break; } - // transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; - // If a FunctionDeclaration has an asterisk token, is exported, or its // subtree has marked the container as needing to capture the lexical `this`, // then this node is ES6 syntax. if ((node).asteriskToken || node.flags & NodeFlags.Export - || subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) { + || subtreeFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)) { transformFlags |= TransformFlags.ThisNodeIsES6; } - // If a FunctionDeclaration is async, or its subtree has marked the container - // as TypeScript, then this node is TypeScript syntax. - if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + // An async function declaration is TypeScript syntax. + if (node.flags & NodeFlags.Async) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; + case SyntaxKind.VariableDeclaration: + // A VariableDeclaration with a binding pattern is ES6 syntax. + if (isBindingPattern((node).name)) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + case SyntaxKind.VariableDeclarationList: // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. - - // transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; if (node.flags & (NodeFlags.Let | NodeFlags.Const)) { transformFlags |= TransformFlags.ThisNodeIsES6; } @@ -1396,31 +1420,40 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - // Class declarations and expressions are ES6 syntax, and exclude markers that should - // not escape the scope of a class. + // A ClassDeclarations or ClassExpression is ES6 syntax. excludeFlags = TransformFlags.ClassDeclarationOrExpressionExcludes; transformFlags = TransformFlags.ThisNodeIsES6; - // If the subtree has marked that the container is TypeScript, then this - // node is TypeScript syntax. - if (subtreeFlags & TransformFlags.ContainerIsTypeScript) { + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxExtensionsMask) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; case SyntaxKind.HeritageClause: - transformFlags |= TransformFlags.ThisNodeIsES6; + // An `extends` HertiageClause is ES6 syntax. + if ((node).token === SyntaxKind.ExtendsKeyword) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } - if ((node).token !== SyntaxKind.ExtendsKeyword || (node).types.length > 1) { + // An `implements` HeritageClause, or an `extends` HeritageClause with more than + // one type must be TypeScript syntax. + if ((node).token !== SyntaxKind.ExtendsKeyword || + (node).types.length > 1) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; case SyntaxKind.ExpressionWithTypeArguments: + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. transformFlags |= TransformFlags.ThisNodeIsES6; + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. if ((node).typeArguments) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } @@ -1428,24 +1461,41 @@ namespace ts { break; case SyntaxKind.Constructor: + // A Constructor is ES6 syntax. excludeFlags = TransformFlags.ConstructorExcludes; transformFlags |= TransformFlags.ThisNodeIsES6; + // An overload constructor is TypeScript syntax. if (!(node).body) { - transformFlags = TransformFlags.ThisNodeIsTypeScript; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.PropertyDeclaration: + // A PropertyDeclaration is TypeScript syntax. + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + + // If the PropertyDeclaration has an initializer, we need to inform its ancestor + // so that it handle the transformation. + if ((node).initializer) { + transformFlags |= TransformFlags.ContainsPropertyInitializer; } break; case SyntaxKind.MethodDeclaration: + // A MethodDeclaration is ES6 syntax. excludeFlags = TransformFlags.MethodDeclarationExcludes; transformFlags |= TransformFlags.ThisNodeIsES6; - if (!(node).body) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - if (node.flags & (NodeFlags.Async | NodeFlags.Abstract) || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has both a computed property name and a decorator. + if ((node).body === undefined || + (node).typeParameters !== undefined || + node.flags & (NodeFlags.Async | NodeFlags.Abstract) || + subtreeFlags & TransformFlags.ContainsDecorator && + subtreeFlags & TransformFlags.ContainsComputedPropertyName) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } @@ -1453,41 +1503,39 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + // A GetAccessor or SetAccessor is ES5 syntax. excludeFlags = TransformFlags.GetOrSetAccessorExcludes; - if (subtreeFlags & TransformFlags.ContainerIsTypeScript) { + + // A GetAccessor or SetAccessor is TypeScript syntax if it is either abstract, + // or has both a computed property name and a decorator. + if (node.flags & NodeFlags.Abstract || + subtreeFlags & TransformFlags.ContainsDecorator && + subtreeFlags & TransformFlags.ContainsComputedPropertyName) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; - // case SyntaxKind.ImportDeclaration: - // case SyntaxKind.ExportDeclaration: - // // Even though these are ES Syntax, we treat them as TypeScript Syntax to support - // // AMD/SystemJS/etc. - // transformFlags |= TransformFlags.ThisNodeIsTypeScript; - // break; - case SyntaxKind.ImportEqualsDeclaration: - // An ImportEqualsDeclaration is TypeScriptwith a namespace reference is TypeScript. + // An ImportEqualsDeclaration with a namespace reference is TypeScript. if (!isExternalModuleImportEqualsDeclaration(node)) { transformFlags |= TransformFlags.ThisNodeIsTypeScript; } break; - // case SyntaxKind.ExportAssignment: - // // An ExportAssignment that is an `export =` will be - // // handled by the emitter and not the transformer. - // if (!(node).isExportEquals) { - // transformFlags |= TransformFlags.ThisNodeIsES6; - // } + case SyntaxKind.PropertyAccessExpression: + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if ((node).expression.kind === SyntaxKind.SuperKeyword) { + transformFlags |= TransformFlags.ContainsLexicalThis; + } - // break; + break; - default: - if (SyntaxKind.FirstTypeNode <= kind && kind <= SyntaxKind.LastTypeNode) { - excludeFlags = TransformFlags.TypeExcludes; - transformFlags |= TransformFlags.ThisNodeIsTypeScript; + case SyntaxKind.SourceFile: + if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) { + transformFlags |= TransformFlags.ThisNodeIsES6; } break; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 122f9714460..548deb54c78 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14649,7 +14649,9 @@ namespace ts { // Return true if the given node is a declaration of a nested block scoped entity with a name that hides an // existing name. function isNestedRedeclaration(node: Declaration): boolean { - return isNestedRedeclarationSymbol(getSymbolOfNode(getOriginalNode(node))); + let original = getOriginalNode(node); + let symbol = !nodeIsSynthesized(original) && getSymbolOfNode(original); + return symbol && isNestedRedeclarationSymbol(getSymbolOfNode(original)); } function isValueAliasDeclaration(node: Node): boolean { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index fc3f7028da7..df8f56d6654 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -390,16 +390,6 @@ namespace ts { return result; } - export function assign(target: Map, source: Map): Map { - if (!target) { - target = {}; - } - for (let id in source) { - target[id] = source[id]; - } - return target; - } - export function forEachValue(map: Map, callback: (value: T) => U): U { let result: U; for (let id in map) { @@ -925,18 +915,18 @@ namespace ts { */ export function createParentNavigator(currentNode: Node): ParentNavigator { /** Gets the grandparent of the current node, without moving the navigator. */ - function getGrandparent() { - let parent = getParent(); + function getGrandparentNode() { + let parent = getParentNode(); return parent ? parent.parent : undefined; } /** Gets the parent of the current node, without moving the navigator. */ - function getParent() { + function getParentNode() { return currentNode ? currentNode.parent : undefined; } /** Gets the current node. */ - function getNode() { + function getCurrentNode() { return currentNode; } @@ -947,7 +937,7 @@ namespace ts { /** Navigates to the parent of the current node if it has one. */ function moveToParent(): boolean { - let parent = getParent(); + let parent = getParentNode(); if (parent) { currentNode = parent; return true; @@ -962,9 +952,9 @@ namespace ts { } return { - getGrandparent, - getParent, - getNode, + getGrandparentNode, + getParentNode, + getCurrentNode, getKind, moveToParent, createParentNavigator, @@ -981,18 +971,22 @@ namespace ts { let parentNode: Node; let currentNode: Node; + function getStackSize(): number { + return stackSize; + } + /** Gets the node two steps back from the top of the stack. */ - function getGrandparent() { + function getGrandparentNode() { return peekNode(2); } /** Gets the node one step back from the top of the stack. */ - function getParent() { + function getParentNode() { return parentNode; } /** Gets the node at the top of the stack. */ - function getNode() { + function getCurrentNode() { return currentNode; } @@ -1073,29 +1067,29 @@ namespace ts { /** Creates a parent navigator a specified number of steps back from the top of the stack. */ function createParentNavigatorFromStackOffset(stackOffset: number): ParentNavigator { /** Gets the node two steps back from the current stack offset. */ - function getGrandparent() { + function getGrandparentNode() { return peekNode(stackOffset + 2); } /** Gets the node one step back from the current stack offset. */ - function getParent() { + function getParentNode() { return peekNode(stackOffset + 1); } /** Gets the node at the current stack offset. */ - function getNode() { + function getCurrentNode() { return peekNode(stackOffset); } /** Gets the SyntaxKind of the node at the current stack offset. */ function getKind() { - let node = getNode(); + let node = getCurrentNode(); return node ? node.kind : undefined; } /** Navigates to the node one step back from the current stack offset. */ function moveToParent() { - if (getParent()) { + if (getParentNode()) { stackOffset++; return true; } @@ -1119,9 +1113,9 @@ namespace ts { } return { - getGrandparent, - getParent, - getNode, + getGrandparentNode, + getParentNode, + getCurrentNode, getKind, moveToParent, createParentNavigator, @@ -1129,9 +1123,10 @@ namespace ts { } return { - getGrandparent, - getParent, - getNode, + getStackSize, + getGrandparentNode, + getParentNode, + getCurrentNode, getKind, pushNode, tryPushNode, diff --git a/src/compiler/factory.generated.ts b/src/compiler/factory.generated.ts index 8af35964dcb..96819bb316c 100644 --- a/src/compiler/factory.generated.ts +++ b/src/compiler/factory.generated.ts @@ -74,13 +74,6 @@ namespace ts { if (expression) node.expression = expression; return node; } - export function createTypeParameter(name?: Identifier, constraint?: TypeNode, expression?: Expression, location?: TextRange, flags?: NodeFlags): TypeParameterDeclaration { - let node = createNode(SyntaxKind.TypeParameter, location, flags); - if (name) node.name = name; - if (constraint) node.constraint = constraint; - if (expression) node.expression = expression; - return node; - } export function createParameter(decorators?: Array, modifiers?: Array, dotDotDotToken?: Node, name?: BindingPattern | Identifier, questionToken?: Node, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): ParameterDeclaration { let node = createNode(SyntaxKind.Parameter, location, flags); if (decorators) node.decorators = createNodeArray(decorators); @@ -97,15 +90,6 @@ namespace ts { if (expression) node.expression = expression; return node; } - export function createPropertySignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, type?: TypeNode, location?: TextRange, flags?: NodeFlags): PropertySignature { - let node = createNode(SyntaxKind.PropertySignature, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (name) node.name = name; - if (questionToken) node.questionToken = questionToken; - if (type) node.type = type; - return node; - } export function createPropertyDeclaration(decorators?: Array, modifiers?: Array, name?: PropertyName, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyDeclaration { let node = createNode(SyntaxKind.PropertyDeclaration, location, flags); if (decorators) node.decorators = createNodeArray(decorators); @@ -115,17 +99,6 @@ namespace ts { if (initializer) node.initializer = initializer; return node; } - export function createMethodSignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): MethodSignature { - let node = createNode(SyntaxKind.MethodSignature, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (name) node.name = name; - if (questionToken) node.questionToken = questionToken; - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - return node; - } export function createMethodDeclaration(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: PropertyName, typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): MethodDeclaration { let node = createNode(SyntaxKind.MethodDeclaration, location, flags); if (decorators) node.decorators = createNodeArray(decorators); @@ -167,92 +140,6 @@ namespace ts { if (body) node.body = body; return node; } - export function createCallSignature(typeParameters?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): CallSignatureDeclaration { - let node = createNode(SyntaxKind.CallSignature, location, flags); - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - if (questionToken) node.questionToken = questionToken; - return node; - } - export function createConstructSignature(typeParameters?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): ConstructSignatureDeclaration { - let node = createNode(SyntaxKind.ConstructSignature, location, flags); - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - if (questionToken) node.questionToken = questionToken; - return node; - } - export function createIndexSignature(decorators?: Array, modifiers?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): IndexSignatureDeclaration { - let node = createNode(SyntaxKind.IndexSignature, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - if (questionToken) node.questionToken = questionToken; - return node; - } - export function createTypePredicate(parameterName?: Identifier, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypePredicateNode { - let node = createNode(SyntaxKind.TypePredicate, location, flags); - if (parameterName) node.parameterName = parameterName; - if (type) node.type = type; - return node; - } - export function createTypeReference(typeName?: EntityName, typeArguments?: Array, location?: TextRange, flags?: NodeFlags): TypeReferenceNode { - let node = createNode(SyntaxKind.TypeReference, location, flags); - if (typeName) node.typeName = typeName; - if (typeArguments) node.typeArguments = createNodeArray(typeArguments); - return node; - } - export function createFunctionType(typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): FunctionTypeNode { - let node = createNode(SyntaxKind.FunctionType, location, flags); - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - return node; - } - export function createConstructorType(typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): ConstructorTypeNode { - let node = createNode(SyntaxKind.ConstructorType, location, flags); - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - return node; - } - export function createTypeQuery(exprName?: EntityName, location?: TextRange, flags?: NodeFlags): TypeQueryNode { - let node = createNode(SyntaxKind.TypeQuery, location, flags); - if (exprName) node.exprName = exprName; - return node; - } - export function createTypeLiteral(members?: Array, location?: TextRange, flags?: NodeFlags): TypeLiteralNode { - let node = createNode(SyntaxKind.TypeLiteral, location, flags); - if (members) node.members = createNodeArray(members); - return node; - } - export function createArrayType(elementType?: TypeNode, location?: TextRange, flags?: NodeFlags): ArrayTypeNode { - let node = createNode(SyntaxKind.ArrayType, location, flags); - if (elementType) node.elementType = elementType; - return node; - } - export function createTupleType(elementTypes?: Array, location?: TextRange, flags?: NodeFlags): TupleTypeNode { - let node = createNode(SyntaxKind.TupleType, location, flags); - if (elementTypes) node.elementTypes = createNodeArray(elementTypes); - return node; - } - export function createUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): UnionTypeNode { - let node = createNode(SyntaxKind.UnionType, location, flags); - if (types) node.types = createNodeArray(types); - return node; - } - export function createIntersectionType(types?: Array, location?: TextRange, flags?: NodeFlags): IntersectionTypeNode { - let node = createNode(SyntaxKind.IntersectionType, location, flags); - if (types) node.types = createNodeArray(types); - return node; - } - export function createParenthesizedType(type?: TypeNode, location?: TextRange, flags?: NodeFlags): ParenthesizedTypeNode { - let node = createNode(SyntaxKind.ParenthesizedType, location, flags); - if (type) node.type = type; - return node; - } export function createObjectBindingPattern(elements?: Array, location?: TextRange, flags?: NodeFlags): ObjectBindingPattern { let node = createNode(SyntaxKind.ObjectBindingPattern, location, flags); if (elements) node.elements = createNodeArray(elements); @@ -594,25 +481,6 @@ namespace ts { if (members) node.members = createNodeArray(members); return node; } - export function createInterfaceDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, heritageClauses?: Array, members?: Array, location?: TextRange, flags?: NodeFlags): InterfaceDeclaration { - let node = createNode(SyntaxKind.InterfaceDeclaration, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (name) node.name = name; - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (heritageClauses) node.heritageClauses = createNodeArray(heritageClauses); - if (members) node.members = createNodeArray(members); - return node; - } - export function createTypeAliasDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypeAliasDeclaration { - let node = createNode(SyntaxKind.TypeAliasDeclaration, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (name) node.name = name; - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (type) node.type = type; - return node; - } export function createEnumDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, members?: Array, location?: TextRange, flags?: NodeFlags): EnumDeclaration { let node = createNode(SyntaxKind.EnumDeclaration, location, flags); if (decorators) node.decorators = createNodeArray(decorators); @@ -703,13 +571,6 @@ namespace ts { if (name) node.name = name; return node; } - export function createMissingDeclaration(decorators?: Array, modifiers?: Array, questionToken?: Node, location?: TextRange, flags?: NodeFlags): MissingDeclaration { - let node = createNode(SyntaxKind.MissingDeclaration, location, flags); - if (decorators) node.decorators = createNodeArray(decorators); - if (modifiers) setModifiers(node, modifiers); - if (questionToken) node.questionToken = questionToken; - return node; - } export function createExternalModuleReference(expression?: Expression, location?: TextRange, flags?: NodeFlags): ExternalModuleReference { let node = createNode(SyntaxKind.ExternalModuleReference, location, flags); if (expression) node.expression = expression; @@ -823,138 +684,6 @@ namespace ts { if (imports) node.imports = imports; return node; } - export function createJSDocTypeExpression(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocTypeExpression { - let node = createNode(SyntaxKind.JSDocTypeExpression, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocAllType(location?: TextRange, flags?: NodeFlags): JSDocAllType { - let node = createNode(SyntaxKind.JSDocAllType, location, flags); - return node; - } - export function createJSDocUnknownType(location?: TextRange, flags?: NodeFlags): JSDocUnknownType { - let node = createNode(SyntaxKind.JSDocUnknownType, location, flags); - return node; - } - export function createJSDocArrayType(elementType?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocArrayType { - let node = createNode(SyntaxKind.JSDocArrayType, location, flags); - if (elementType) node.elementType = elementType; - return node; - } - export function createJSDocUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocUnionType { - let node = createNode(SyntaxKind.JSDocUnionType, location, flags); - if (types) node.types = createNodeArray(types); - return node; - } - export function createJSDocTupleType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocTupleType { - let node = createNode(SyntaxKind.JSDocTupleType, location, flags); - if (types) node.types = createNodeArray(types); - return node; - } - export function createJSDocNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNullableType { - let node = createNode(SyntaxKind.JSDocNullableType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocNonNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNonNullableType { - let node = createNode(SyntaxKind.JSDocNonNullableType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocRecordType(members?: Array, location?: TextRange, flags?: NodeFlags): JSDocRecordType { - let node = createNode(SyntaxKind.JSDocRecordType, location, flags); - if (members) node.members = createNodeArray(members); - return node; - } - export function createJSDocRecordMember(name?: Identifier | LiteralExpression, type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocRecordMember { - let node = createNode(SyntaxKind.JSDocRecordMember, location, flags); - if (name) node.name = name; - if (type) node.type = type; - return node; - } - export function createJSDocTypeReference(name?: EntityName, typeArguments?: Array, location?: TextRange, flags?: NodeFlags): JSDocTypeReference { - let node = createNode(SyntaxKind.JSDocTypeReference, location, flags); - if (name) node.name = name; - if (typeArguments) node.typeArguments = createNodeArray(typeArguments); - return node; - } - export function createJSDocOptionalType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocOptionalType { - let node = createNode(SyntaxKind.JSDocOptionalType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocFunctionType(parameters?: Array, type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocFunctionType { - let node = createNode(SyntaxKind.JSDocFunctionType, location, flags); - if (parameters) node.parameters = createNodeArray(parameters); - if (type) node.type = type; - return node; - } - export function createJSDocVariadicType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocVariadicType { - let node = createNode(SyntaxKind.JSDocVariadicType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocConstructorType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocConstructorType { - let node = createNode(SyntaxKind.JSDocConstructorType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocThisType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocThisType { - let node = createNode(SyntaxKind.JSDocThisType, location, flags); - if (type) node.type = type; - return node; - } - export function createJSDocComment(tags?: Array, location?: TextRange, flags?: NodeFlags): JSDocComment { - let node = createNode(SyntaxKind.JSDocComment, location, flags); - if (tags) node.tags = createNodeArray(tags); - return node; - } - export function createJSDocTag(atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTag { - let node = createNode(SyntaxKind.JSDocTag, location, flags); - if (atToken) node.atToken = atToken; - if (tagName) node.tagName = tagName; - return node; - } - export function createJSDocParameterTag(preParameterName?: Identifier, typeExpression?: JSDocTypeExpression, postParameterName?: Identifier, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocParameterTag { - let node = createNode(SyntaxKind.JSDocParameterTag, location, flags); - if (preParameterName) node.preParameterName = preParameterName; - if (typeExpression) node.typeExpression = typeExpression; - if (postParameterName) node.postParameterName = postParameterName; - if (atToken) node.atToken = atToken; - if (tagName) node.tagName = tagName; - return node; - } - export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocReturnTag { - let node = createNode(SyntaxKind.JSDocReturnTag, location, flags); - if (typeExpression) node.typeExpression = typeExpression; - if (atToken) node.atToken = atToken; - if (tagName) node.tagName = tagName; - return node; - } - export function createJSDocTypeTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTypeTag { - let node = createNode(SyntaxKind.JSDocTypeTag, location, flags); - if (typeExpression) node.typeExpression = typeExpression; - if (atToken) node.atToken = atToken; - if (tagName) node.tagName = tagName; - return node; - } - export function createJSDocTemplateTag(typeParameters?: Array, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTemplateTag { - let node = createNode(SyntaxKind.JSDocTemplateTag, location, flags); - if (typeParameters) node.typeParameters = createNodeArray(typeParameters); - if (atToken) node.atToken = atToken; - if (tagName) node.tagName = tagName; - return node; - } - export function createRawExpression(text?: string, location?: TextRange, flags?: NodeFlags): RawExpression { - let node = createNode(SyntaxKind.RawExpression, location, flags); - if (text) node.text = text; - return node; - } - export function createRawStatement(text?: string, location?: TextRange, flags?: NodeFlags): RawStatement { - let node = createNode(SyntaxKind.RawStatement, location, flags); - if (text) node.text = text; - return node; - } export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName { if (left !== node.left || right !== node.right) { let newNode = createQualifiedName(left, right); @@ -969,13 +698,6 @@ namespace ts { } return node; } - export function updateTypeParameter(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode, expression: Expression): TypeParameterDeclaration { - if (name !== node.name || constraint !== node.constraint || expression !== node.expression) { - let newNode = createTypeParameter(name, constraint, expression); - return updateFrom(node, newNode); - } - return node; - } export function updateParameter(node: ParameterDeclaration, decorators: Array, modifiers: Array, name: BindingPattern | Identifier, questionToken: Node, type: TypeNode, initializer: Expression): ParameterDeclaration { if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || questionToken !== node.questionToken || type !== node.type || initializer !== node.initializer) { let newNode = createParameter(decorators, modifiers, node.dotDotDotToken, name, questionToken, type, initializer); @@ -990,13 +712,6 @@ namespace ts { } return node; } - export function updatePropertySignature(node: PropertySignature, decorators: Array, modifiers: Array, name: PropertyName, type: TypeNode): PropertySignature { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type) { - let newNode = createPropertySignature(decorators, modifiers, name, node.questionToken, type); - return updateFrom(node, newNode); - } - return node; - } export function updatePropertyDeclaration(node: PropertyDeclaration, decorators: Array, modifiers: Array, name: PropertyName, type: TypeNode, initializer: Expression): PropertyDeclaration { if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type || initializer !== node.initializer) { let newNode = createPropertyDeclaration(decorators, modifiers, name, type, initializer); @@ -1004,13 +719,6 @@ namespace ts { } return node; } - export function updateMethodSignature(node: MethodSignature, decorators: Array, modifiers: Array, name: PropertyName, typeParameters: Array, parameters: Array, type: TypeNode): MethodSignature { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createMethodSignature(decorators, modifiers, name, node.questionToken, typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } export function updateMethodDeclaration(node: MethodDeclaration, decorators: Array, modifiers: Array, name: PropertyName, typeParameters: Array, parameters: Array, type: TypeNode, body: FunctionBody): MethodDeclaration { if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type || body !== node.body) { let newNode = createMethodDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); @@ -1039,104 +747,6 @@ namespace ts { } return node; } - export function updateCallSignature(node: CallSignatureDeclaration, typeParameters: Array, parameters: Array, type: TypeNode): CallSignatureDeclaration { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createCallSignature(typeParameters, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: Array, parameters: Array, type: TypeNode): ConstructSignatureDeclaration { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createConstructSignature(typeParameters, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function updateIndexSignature(node: IndexSignatureDeclaration, decorators: Array, modifiers: Array, parameters: Array, type: TypeNode): IndexSignatureDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || parameters !== node.parameters || type !== node.type) { - let newNode = createIndexSignature(decorators, modifiers, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function updateTypePredicate(node: TypePredicateNode, parameterName: Identifier, type: TypeNode): TypePredicateNode { - if (parameterName !== node.parameterName || type !== node.type) { - let newNode = createTypePredicate(parameterName, type); - return updateFrom(node, newNode); - } - return node; - } - export function updateTypeReference(node: TypeReferenceNode, typeName: EntityName, typeArguments: Array): TypeReferenceNode { - if (typeName !== node.typeName || typeArguments !== node.typeArguments) { - let newNode = createTypeReference(typeName, typeArguments); - return updateFrom(node, newNode); - } - return node; - } - export function updateFunctionType(node: FunctionTypeNode, typeParameters: Array, parameters: Array, type: TypeNode): FunctionTypeNode { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createFunctionType(typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function updateConstructorType(node: ConstructorTypeNode, typeParameters: Array, parameters: Array, type: TypeNode): ConstructorTypeNode { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createConstructorType(typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function updateTypeQuery(node: TypeQueryNode, exprName: EntityName): TypeQueryNode { - if (exprName !== node.exprName) { - let newNode = createTypeQuery(exprName); - return updateFrom(node, newNode); - } - return node; - } - export function updateTypeLiteral(node: TypeLiteralNode, members: Array): TypeLiteralNode { - if (members !== node.members) { - let newNode = createTypeLiteral(members); - return updateFrom(node, newNode); - } - return node; - } - export function updateArrayType(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { - if (elementType !== node.elementType) { - let newNode = createArrayType(elementType); - return updateFrom(node, newNode); - } - return node; - } - export function updateTupleType(node: TupleTypeNode, elementTypes: Array): TupleTypeNode { - if (elementTypes !== node.elementTypes) { - let newNode = createTupleType(elementTypes); - return updateFrom(node, newNode); - } - return node; - } - export function updateUnionType(node: UnionTypeNode, types: Array): UnionTypeNode { - if (types !== node.types) { - let newNode = createUnionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function updateIntersectionType(node: IntersectionTypeNode, types: Array): IntersectionTypeNode { - if (types !== node.types) { - let newNode = createIntersectionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode { - if (type !== node.type) { - let newNode = createParenthesizedType(type); - return updateFrom(node, newNode); - } - return node; - } export function updateObjectBindingPattern(node: ObjectBindingPattern, elements: Array): ObjectBindingPattern { if (elements !== node.elements) { let newNode = createObjectBindingPattern(elements); @@ -1487,20 +1097,6 @@ namespace ts { } return node; } - export function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, heritageClauses: Array, members: Array): InterfaceDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || heritageClauses !== node.heritageClauses || members !== node.members) { - let newNode = createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); - return updateFrom(node, newNode); - } - return node; - } - export function updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, type: TypeNode): TypeAliasDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || type !== node.type) { - let newNode = createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type); - return updateFrom(node, newNode); - } - return node; - } export function updateEnumDeclaration(node: EnumDeclaration, decorators: Array, modifiers: Array, name: Identifier, members: Array): EnumDeclaration { if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || members !== node.members) { let newNode = createEnumDeclaration(decorators, modifiers, name, members); @@ -1599,13 +1195,6 @@ namespace ts { } return node; } - export function updateMissingDeclaration(node: MissingDeclaration, decorators: Array, modifiers: Array): MissingDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers) { - let newNode = createMissingDeclaration(decorators, modifiers, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference { if (expression !== node.expression) { let newNode = createExternalModuleReference(expression); @@ -1718,185 +1307,24 @@ namespace ts { } return node; } - export function updateJSDocTypeExpression(node: JSDocTypeExpression, type: JSDocType): JSDocTypeExpression { - if (type !== node.type) { - let newNode = createJSDocTypeExpression(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocArrayType(node: JSDocArrayType, elementType: JSDocType): JSDocArrayType { - if (elementType !== node.elementType) { - let newNode = createJSDocArrayType(elementType); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocUnionType(node: JSDocUnionType, types: Array): JSDocUnionType { - if (types !== node.types) { - let newNode = createJSDocUnionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocTupleType(node: JSDocTupleType, types: Array): JSDocTupleType { - if (types !== node.types) { - let newNode = createJSDocTupleType(types); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocNullableType(node: JSDocNullableType, type: JSDocType): JSDocNullableType { - if (type !== node.type) { - let newNode = createJSDocNullableType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocNonNullableType(node: JSDocNonNullableType, type: JSDocType): JSDocNonNullableType { - if (type !== node.type) { - let newNode = createJSDocNonNullableType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocRecordType(node: JSDocRecordType, members: Array): JSDocRecordType { - if (members !== node.members) { - let newNode = createJSDocRecordType(members); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocRecordMember(node: JSDocRecordMember, name: Identifier | LiteralExpression, type: JSDocType): JSDocRecordMember { - if (name !== node.name || type !== node.type) { - let newNode = createJSDocRecordMember(name, type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocTypeReference(node: JSDocTypeReference, name: EntityName, typeArguments: Array): JSDocTypeReference { - if (name !== node.name || typeArguments !== node.typeArguments) { - let newNode = createJSDocTypeReference(name, typeArguments); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocOptionalType(node: JSDocOptionalType, type: JSDocType): JSDocOptionalType { - if (type !== node.type) { - let newNode = createJSDocOptionalType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocFunctionType(node: JSDocFunctionType, parameters: Array, type: JSDocType): JSDocFunctionType { - if (parameters !== node.parameters || type !== node.type) { - let newNode = createJSDocFunctionType(parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocVariadicType(node: JSDocVariadicType, type: JSDocType): JSDocVariadicType { - if (type !== node.type) { - let newNode = createJSDocVariadicType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocConstructorType(node: JSDocConstructorType, type: JSDocType): JSDocConstructorType { - if (type !== node.type) { - let newNode = createJSDocConstructorType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocThisType(node: JSDocThisType, type: JSDocType): JSDocThisType { - if (type !== node.type) { - let newNode = createJSDocThisType(type); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocComment(node: JSDocComment, tags: Array): JSDocComment { - if (tags !== node.tags) { - let newNode = createJSDocComment(tags); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocTag(node: JSDocTag, tagName: Identifier): JSDocTag { - if (tagName !== node.tagName) { - let newNode = createJSDocTag(node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocParameterTag(node: JSDocParameterTag, preParameterName: Identifier, typeExpression: JSDocTypeExpression, postParameterName: Identifier, tagName: Identifier): JSDocParameterTag { - if (preParameterName !== node.preParameterName || typeExpression !== node.typeExpression || postParameterName !== node.postParameterName || tagName !== node.tagName) { - let newNode = createJSDocParameterTag(preParameterName, typeExpression, postParameterName, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocReturnTag(node: JSDocReturnTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocReturnTag { - if (typeExpression !== node.typeExpression || tagName !== node.tagName) { - let newNode = createJSDocReturnTag(typeExpression, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocTypeTag(node: JSDocTypeTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocTypeTag { - if (typeExpression !== node.typeExpression || tagName !== node.tagName) { - let newNode = createJSDocTypeTag(typeExpression, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function updateJSDocTemplateTag(node: JSDocTemplateTag, typeParameters: Array, tagName: Identifier): JSDocTemplateTag { - if (typeParameters !== node.typeParameters || tagName !== node.tagName) { - let newNode = createJSDocTemplateTag(typeParameters, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } export function isNumericLiteral(node: Node): node is LiteralExpression { return node && node.kind === SyntaxKind.NumericLiteral; } export function isStringLiteral(node: Node): node is StringLiteral { return node && node.kind === SyntaxKind.StringLiteral; } - export function isRegularExpressionLiteral(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.RegularExpressionLiteral; - } export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression { return node && node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; } - export function isTemplateHead(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateHead; - } - export function isTemplateMiddle(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateMiddle; - } - export function isTemplateTail(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateTail; - } export function isIdentifier(node: Node): node is Identifier { return node && node.kind === SyntaxKind.Identifier; } - export function isFalseKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.FalseKeyword; - } - export function isNullKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.NullKeyword; - } export function isSuperKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.SuperKeyword; } export function isThisKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.ThisKeyword; } - export function isTrueKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.TrueKeyword; - } export function isQualifiedName(node: Node): node is QualifiedName { return node && node.kind === SyntaxKind.QualifiedName; } @@ -1912,15 +1340,9 @@ namespace ts { export function isDecorator(node: Node): node is Decorator { return node && node.kind === SyntaxKind.Decorator; } - export function isPropertySignature(node: Node): node is PropertySignature { - return node && node.kind === SyntaxKind.PropertySignature; - } export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { return node && node.kind === SyntaxKind.PropertyDeclaration; } - export function isMethodSignature(node: Node): node is MethodSignature { - return node && node.kind === SyntaxKind.MethodSignature; - } export function isMethodDeclaration(node: Node): node is MethodDeclaration { return node && node.kind === SyntaxKind.MethodDeclaration; } @@ -1933,48 +1355,12 @@ namespace ts { export function isSetAccessor(node: Node): node is SetAccessorDeclaration { return node && node.kind === SyntaxKind.SetAccessor; } - export function isCallSignature(node: Node): node is CallSignatureDeclaration { - return node && node.kind === SyntaxKind.CallSignature; - } - export function isConstructSignature(node: Node): node is ConstructSignatureDeclaration { - return node && node.kind === SyntaxKind.ConstructSignature; - } - export function isIndexSignature(node: Node): node is IndexSignatureDeclaration { - return node && node.kind === SyntaxKind.IndexSignature; - } - export function isTypePredicate(node: Node): node is TypePredicateNode { - return node && node.kind === SyntaxKind.TypePredicate; - } export function isTypeReference(node: Node): node is TypeReferenceNode { return node && node.kind === SyntaxKind.TypeReference; } - export function isFunctionType(node: Node): node is FunctionTypeNode { - return node && node.kind === SyntaxKind.FunctionType; - } - export function isConstructorType(node: Node): node is ConstructorTypeNode { - return node && node.kind === SyntaxKind.ConstructorType; - } - export function isTypeQuery(node: Node): node is TypeQueryNode { - return node && node.kind === SyntaxKind.TypeQuery; - } - export function isTypeLiteral(node: Node): node is TypeLiteralNode { - return node && node.kind === SyntaxKind.TypeLiteral; - } export function isArrayType(node: Node): node is ArrayTypeNode { return node && node.kind === SyntaxKind.ArrayType; } - export function isTupleType(node: Node): node is TupleTypeNode { - return node && node.kind === SyntaxKind.TupleType; - } - export function isUnionType(node: Node): node is UnionTypeNode { - return node && node.kind === SyntaxKind.UnionType; - } - export function isIntersectionType(node: Node): node is IntersectionTypeNode { - return node && node.kind === SyntaxKind.IntersectionType; - } - export function isParenthesizedType(node: Node): node is ParenthesizedTypeNode { - return node && node.kind === SyntaxKind.ParenthesizedType; - } export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { return node && node.kind === SyntaxKind.ObjectBindingPattern; } @@ -2017,18 +1403,6 @@ namespace ts { export function isArrowFunction(node: Node): node is ArrowFunction { return node && node.kind === SyntaxKind.ArrowFunction; } - export function isDeleteExpression(node: Node): node is DeleteExpression { - return node && node.kind === SyntaxKind.DeleteExpression; - } - export function isTypeOfExpression(node: Node): node is TypeOfExpression { - return node && node.kind === SyntaxKind.TypeOfExpression; - } - export function isVoidExpression(node: Node): node is VoidExpression { - return node && node.kind === SyntaxKind.VoidExpression; - } - export function isAwaitExpression(node: Node): node is AwaitExpression { - return node && node.kind === SyntaxKind.AwaitExpression; - } export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { return node && node.kind === SyntaxKind.PrefixUnaryExpression; } @@ -2044,9 +1418,6 @@ namespace ts { export function isTemplateExpression(node: Node): node is TemplateExpression { return node && node.kind === SyntaxKind.TemplateExpression; } - export function isYieldExpression(node: Node): node is YieldExpression { - return node && node.kind === SyntaxKind.YieldExpression; - } export function isSpreadElementExpression(node: Node): node is SpreadElementExpression { return node && node.kind === SyntaxKind.SpreadElementExpression; } @@ -2071,12 +1442,6 @@ namespace ts { export function isBlock(node: Node): node is Block { return node && node.kind === SyntaxKind.Block; } - export function isVariableStatement(node: Node): node is VariableStatement { - return node && node.kind === SyntaxKind.VariableStatement; - } - export function isEmptyStatement(node: Node): node is EmptyStatement { - return node && node.kind === SyntaxKind.EmptyStatement; - } export function isExpressionStatement(node: Node): node is ExpressionStatement { return node && node.kind === SyntaxKind.ExpressionStatement; } @@ -2098,33 +1463,9 @@ namespace ts { export function isForOfStatement(node: Node): node is ForOfStatement { return node && node.kind === SyntaxKind.ForOfStatement; } - export function isContinueStatement(node: Node): node is ContinueStatement { - return node && node.kind === SyntaxKind.ContinueStatement; - } - export function isBreakStatement(node: Node): node is BreakStatement { - return node && node.kind === SyntaxKind.BreakStatement; - } export function isReturnStatement(node: Node): node is ReturnStatement { return node && node.kind === SyntaxKind.ReturnStatement; } - export function isWithStatement(node: Node): node is WithStatement { - return node && node.kind === SyntaxKind.WithStatement; - } - export function isSwitchStatement(node: Node): node is SwitchStatement { - return node && node.kind === SyntaxKind.SwitchStatement; - } - export function isLabeledStatement(node: Node): node is LabeledStatement { - return node && node.kind === SyntaxKind.LabeledStatement; - } - export function isThrowStatement(node: Node): node is ThrowStatement { - return node && node.kind === SyntaxKind.ThrowStatement; - } - export function isTryStatement(node: Node): node is TryStatement { - return node && node.kind === SyntaxKind.TryStatement; - } - export function isDebuggerStatement(node: Node): node is DebuggerStatement { - return node && node.kind === SyntaxKind.DebuggerStatement; - } export function isVariableDeclaration(node: Node): node is VariableDeclaration { return node && node.kind === SyntaxKind.VariableDeclaration; } @@ -2137,15 +1478,6 @@ namespace ts { export function isClassDeclaration(node: Node): node is ClassDeclaration { return node && node.kind === SyntaxKind.ClassDeclaration; } - export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { - return node && node.kind === SyntaxKind.InterfaceDeclaration; - } - export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { - return node && node.kind === SyntaxKind.TypeAliasDeclaration; - } - export function isEnumDeclaration(node: Node): node is EnumDeclaration { - return node && node.kind === SyntaxKind.EnumDeclaration; - } export function isModuleDeclaration(node: Node): node is ModuleDeclaration { return node && node.kind === SyntaxKind.ModuleDeclaration; } @@ -2185,12 +1517,6 @@ namespace ts { export function isExportSpecifier(node: Node): node is ExportSpecifier { return node && node.kind === SyntaxKind.ExportSpecifier; } - export function isMissingDeclaration(node: Node): node is MissingDeclaration { - return node && node.kind === SyntaxKind.MissingDeclaration; - } - export function isExternalModuleReference(node: Node): node is ExternalModuleReference { - return node && node.kind === SyntaxKind.ExternalModuleReference; - } export function isJsxElement(node: Node): node is JsxElement { return node && node.kind === SyntaxKind.JsxElement; } @@ -2206,21 +1532,12 @@ namespace ts { export function isJsxClosingElement(node: Node): node is JsxClosingElement { return node && node.kind === SyntaxKind.JsxClosingElement; } - export function isJsxAttribute(node: Node): node is JsxAttribute { - return node && node.kind === SyntaxKind.JsxAttribute; - } export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { return node && node.kind === SyntaxKind.JsxSpreadAttribute; } export function isJsxExpression(node: Node): node is JsxExpression { return node && node.kind === SyntaxKind.JsxExpression; } - export function isCaseClause(node: Node): node is CaseClause { - return node && node.kind === SyntaxKind.CaseClause; - } - export function isDefaultClause(node: Node): node is DefaultClause { - return node && node.kind === SyntaxKind.DefaultClause; - } export function isHeritageClause(node: Node): node is HeritageClause { return node && node.kind === SyntaxKind.HeritageClause; } @@ -2239,78 +1556,6 @@ namespace ts { export function isSourceFile(node: Node): node is SourceFile { return node && node.kind === SyntaxKind.SourceFile; } - export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { - return node && node.kind === SyntaxKind.JSDocTypeExpression; - } - export function isJSDocAllType(node: Node): node is JSDocAllType { - return node && node.kind === SyntaxKind.JSDocAllType; - } - export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { - return node && node.kind === SyntaxKind.JSDocUnknownType; - } - export function isJSDocArrayType(node: Node): node is JSDocArrayType { - return node && node.kind === SyntaxKind.JSDocArrayType; - } - export function isJSDocUnionType(node: Node): node is JSDocUnionType { - return node && node.kind === SyntaxKind.JSDocUnionType; - } - export function isJSDocTupleType(node: Node): node is JSDocTupleType { - return node && node.kind === SyntaxKind.JSDocTupleType; - } - export function isJSDocNullableType(node: Node): node is JSDocNullableType { - return node && node.kind === SyntaxKind.JSDocNullableType; - } - export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { - return node && node.kind === SyntaxKind.JSDocNonNullableType; - } - export function isJSDocRecordType(node: Node): node is JSDocRecordType { - return node && node.kind === SyntaxKind.JSDocRecordType; - } - export function isJSDocRecordMember(node: Node): node is JSDocRecordMember { - return node && node.kind === SyntaxKind.JSDocRecordMember; - } - export function isJSDocTypeReference(node: Node): node is JSDocTypeReference { - return node && node.kind === SyntaxKind.JSDocTypeReference; - } - export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { - return node && node.kind === SyntaxKind.JSDocOptionalType; - } - export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { - return node && node.kind === SyntaxKind.JSDocFunctionType; - } - export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { - return node && node.kind === SyntaxKind.JSDocVariadicType; - } - export function isJSDocConstructorType(node: Node): node is JSDocConstructorType { - return node && node.kind === SyntaxKind.JSDocConstructorType; - } - export function isJSDocThisType(node: Node): node is JSDocThisType { - return node && node.kind === SyntaxKind.JSDocThisType; - } - export function isJSDocComment(node: Node): node is JSDocComment { - return node && node.kind === SyntaxKind.JSDocComment; - } - export function isJSDocTag(node: Node): node is JSDocTag { - return node && node.kind === SyntaxKind.JSDocTag; - } - export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { - return node && node.kind === SyntaxKind.JSDocParameterTag; - } - export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { - return node && node.kind === SyntaxKind.JSDocReturnTag; - } - export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { - return node && node.kind === SyntaxKind.JSDocTypeTag; - } - export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { - return node && node.kind === SyntaxKind.JSDocTemplateTag; - } - export function isRawExpression(node: Node): node is RawExpression { - return node && node.kind === SyntaxKind.RawExpression; - } - export function isRawStatement(node: Node): node is RawStatement { - return node && node.kind === SyntaxKind.RawStatement; - } export function isFunctionBody(node: Node): node is FunctionBody { if (node) { switch (node.kind) { @@ -2354,7 +1599,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.FunctionExpression: @@ -2413,7 +1657,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: return true; } } @@ -2431,7 +1674,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: return true; } } @@ -2451,7 +1693,6 @@ namespace ts { case SyntaxKind.ExportDeclaration: case SyntaxKind.ExportAssignment: case SyntaxKind.Block: - case SyntaxKind.RawStatement: case SyntaxKind.EmptyStatement: case SyntaxKind.DebuggerStatement: case SyntaxKind.ModuleBlock: @@ -2480,6 +1721,12 @@ namespace ts { export function isTypeNodeNode(node: Node): node is TypeNode { if (node) { switch (node.kind) { + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: case SyntaxKind.TypeReference: @@ -2584,7 +1831,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.FunctionExpression: @@ -2620,7 +1866,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: return true; } } @@ -2642,7 +1887,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.FunctionExpression: @@ -2688,7 +1932,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: case SyntaxKind.TemplateExpression: return true; } @@ -2733,7 +1976,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.FunctionExpression: @@ -2800,7 +2042,6 @@ namespace ts { case SyntaxKind.TemplateMiddle: case SyntaxKind.TemplateTail: case SyntaxKind.StringLiteral: - case SyntaxKind.RawExpression: return true; } } @@ -2827,494 +2068,6 @@ namespace ts { } return false; } - export function isJSDocType(node: Node): node is JSDocType { - if (node) { - switch (node.kind) { - case SyntaxKind.JSDocAllType: - case SyntaxKind.JSDocUnknownType: - case SyntaxKind.JSDocArrayType: - case SyntaxKind.JSDocUnionType: - case SyntaxKind.JSDocTupleType: - case SyntaxKind.JSDocNonNullableType: - case SyntaxKind.JSDocNullableType: - case SyntaxKind.JSDocRecordType: - case SyntaxKind.JSDocTypeReference: - case SyntaxKind.JSDocOptionalType: - case SyntaxKind.JSDocFunctionType: - case SyntaxKind.JSDocVariadicType: - case SyntaxKind.JSDocConstructorType: - case SyntaxKind.JSDocThisType: - return true; - } - } - return false; - } - export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode; - export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node { - if (node) { - let clone: Node; - switch (node.kind) { - case SyntaxKind.NumericLiteral: - clone = createNumericLiteral((node).text, location, flags); - break; - case SyntaxKind.StringLiteral: - clone = createStringLiteral((node).text, location, flags); - break; - case SyntaxKind.RegularExpressionLiteral: - clone = createRegularExpressionLiteral((node).text, location, flags); - break; - case SyntaxKind.NoSubstitutionTemplateLiteral: - clone = createNoSubstitutionTemplateLiteral((node).text, location, flags); - break; - case SyntaxKind.TemplateHead: - clone = createTemplateHead((node).text, location, flags); - break; - case SyntaxKind.TemplateMiddle: - clone = createTemplateMiddle((node).text, location, flags); - break; - case SyntaxKind.TemplateTail: - clone = createTemplateTail((node).text, location, flags); - break; - case SyntaxKind.Identifier: - clone = createIdentifier((node).text, (node).originalKeywordKind, location, flags); - break; - case SyntaxKind.FalseKeyword: - clone = createFalseKeyword(location, flags); - break; - case SyntaxKind.NullKeyword: - clone = createNullKeyword(location, flags); - break; - case SyntaxKind.SuperKeyword: - clone = createSuperKeyword(location, flags); - break; - case SyntaxKind.ThisKeyword: - clone = createThisKeyword(location, flags); - break; - case SyntaxKind.TrueKeyword: - clone = createTrueKeyword(location, flags); - break; - case SyntaxKind.QualifiedName: - clone = createQualifiedName((node).left, (node).right, location, flags); - break; - case SyntaxKind.ComputedPropertyName: - clone = createComputedPropertyName((node).expression, location, flags); - break; - case SyntaxKind.TypeParameter: - clone = createTypeParameter((node).name, (node).constraint, (node).expression, location, flags); - break; - case SyntaxKind.Parameter: - clone = createParameter((node).decorators, (node).modifiers, (node).dotDotDotToken, (node).name, (node).questionToken, (node).type, (node).initializer, location, flags); - break; - case SyntaxKind.Decorator: - clone = createDecorator((node).expression, location, flags); - break; - case SyntaxKind.PropertySignature: - clone = createPropertySignature((node).decorators, (node).modifiers, (node).name, (node).questionToken, (node).type, location, flags); - break; - case SyntaxKind.PropertyDeclaration: - clone = createPropertyDeclaration((node).decorators, (node).modifiers, (node).name, (node).type, (node).initializer, location, flags); - break; - case SyntaxKind.MethodSignature: - clone = createMethodSignature((node).decorators, (node).modifiers, (node).name, (node).questionToken, (node).typeParameters, (node).parameters, (node).type, location, flags); - break; - case SyntaxKind.MethodDeclaration: - clone = createMethodDeclaration((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.Constructor: - clone = createConstructor((node).decorators, (node).modifiers, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.GetAccessor: - clone = createGetAccessor((node).decorators, (node).modifiers, (node).name, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.SetAccessor: - clone = createSetAccessor((node).decorators, (node).modifiers, (node).name, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.CallSignature: - clone = createCallSignature((node).typeParameters, (node).parameters, (node).type, (node).questionToken, location, flags); - break; - case SyntaxKind.ConstructSignature: - clone = createConstructSignature((node).typeParameters, (node).parameters, (node).type, (node).questionToken, location, flags); - break; - case SyntaxKind.IndexSignature: - clone = createIndexSignature((node).decorators, (node).modifiers, (node).parameters, (node).type, (node).questionToken, location, flags); - break; - case SyntaxKind.TypePredicate: - clone = createTypePredicate((node).parameterName, (node).type, location, flags); - break; - case SyntaxKind.TypeReference: - clone = createTypeReference((node).typeName, (node).typeArguments, location, flags); - break; - case SyntaxKind.FunctionType: - clone = createFunctionType((node).typeParameters, (node).parameters, (node).type, location, flags); - break; - case SyntaxKind.ConstructorType: - clone = createConstructorType((node).typeParameters, (node).parameters, (node).type, location, flags); - break; - case SyntaxKind.TypeQuery: - clone = createTypeQuery((node).exprName, location, flags); - break; - case SyntaxKind.TypeLiteral: - clone = createTypeLiteral((node).members, location, flags); - break; - case SyntaxKind.ArrayType: - clone = createArrayType((node).elementType, location, flags); - break; - case SyntaxKind.TupleType: - clone = createTupleType((node).elementTypes, location, flags); - break; - case SyntaxKind.UnionType: - clone = createUnionType((node).types, location, flags); - break; - case SyntaxKind.IntersectionType: - clone = createIntersectionType((node).types, location, flags); - break; - case SyntaxKind.ParenthesizedType: - clone = createParenthesizedType((node).type, location, flags); - break; - case SyntaxKind.ObjectBindingPattern: - clone = createObjectBindingPattern((node).elements, location, flags); - break; - case SyntaxKind.ArrayBindingPattern: - clone = createArrayBindingPattern((node).elements, location, flags); - break; - case SyntaxKind.BindingElement: - clone = createBindingElement((node).propertyName, (node).dotDotDotToken, (node).name, (node).initializer, location, flags); - break; - case SyntaxKind.ArrayLiteralExpression: - clone = createArrayLiteralExpression((node).elements, location, flags); - break; - case SyntaxKind.ObjectLiteralExpression: - clone = createObjectLiteralExpression((node).properties, location, flags); - break; - case SyntaxKind.PropertyAccessExpression: - clone = createPropertyAccessExpression((node).expression, (node).dotToken, (node).name, location, flags); - break; - case SyntaxKind.ElementAccessExpression: - clone = createElementAccessExpression((node).expression, (node).argumentExpression, location, flags); - break; - case SyntaxKind.CallExpression: - clone = createCallExpression((node).expression, (node).typeArguments, (node).arguments, location, flags); - break; - case SyntaxKind.NewExpression: - clone = createNewExpression((node).expression, (node).typeArguments, (node).arguments, location, flags); - break; - case SyntaxKind.TaggedTemplateExpression: - clone = createTaggedTemplateExpression((node).tag, (node).template, location, flags); - break; - case SyntaxKind.TypeAssertionExpression: - clone = createTypeAssertionExpression((node).type, (node).expression, location, flags); - break; - case SyntaxKind.ParenthesizedExpression: - clone = createParenthesizedExpression((node).expression, location, flags); - break; - case SyntaxKind.FunctionExpression: - clone = createFunctionExpression((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.ArrowFunction: - clone = createArrowFunction((node).decorators, (node).modifiers, (node).typeParameters, (node).parameters, (node).type, (node).equalsGreaterThanToken, (node).body, location, flags); - break; - case SyntaxKind.DeleteExpression: - clone = createDeleteExpression((node).expression, location, flags); - break; - case SyntaxKind.TypeOfExpression: - clone = createTypeOfExpression((node).expression, location, flags); - break; - case SyntaxKind.VoidExpression: - clone = createVoidExpression((node).expression, location, flags); - break; - case SyntaxKind.AwaitExpression: - clone = createAwaitExpression((node).expression, location, flags); - break; - case SyntaxKind.PrefixUnaryExpression: - clone = createPrefixUnaryExpression((node).operator, (node).operand, location, flags); - break; - case SyntaxKind.PostfixUnaryExpression: - clone = createPostfixUnaryExpression((node).operand, (node).operator, location, flags); - break; - case SyntaxKind.BinaryExpression: - clone = createBinaryExpression((node).left, (node).operatorToken, (node).right, location, flags); - break; - case SyntaxKind.ConditionalExpression: - clone = createConditionalExpression((node).condition, (node).questionToken, (node).whenTrue, (node).colonToken, (node).whenFalse, location, flags); - break; - case SyntaxKind.TemplateExpression: - clone = createTemplateExpression((node).head, (node).templateSpans, location, flags); - break; - case SyntaxKind.YieldExpression: - clone = createYieldExpression((node).asteriskToken, (node).expression, location, flags); - break; - case SyntaxKind.SpreadElementExpression: - clone = createSpreadElementExpression((node).expression, location, flags); - break; - case SyntaxKind.ClassExpression: - clone = createClassExpression((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); - break; - case SyntaxKind.OmittedExpression: - clone = createOmittedExpression(location, flags); - break; - case SyntaxKind.ExpressionWithTypeArguments: - clone = createExpressionWithTypeArguments((node).expression, (node).typeArguments, location, flags); - break; - case SyntaxKind.AsExpression: - clone = createAsExpression((node).expression, (node).type, location, flags); - break; - case SyntaxKind.TemplateSpan: - clone = createTemplateSpan((node).expression, (node).literal, location, flags); - break; - case SyntaxKind.SemicolonClassElement: - clone = createSemicolonClassElement(location, flags); - break; - case SyntaxKind.Block: - clone = createBlock((node).statements, location, flags); - break; - case SyntaxKind.VariableStatement: - clone = createVariableStatement((node).decorators, (node).modifiers, (node).declarationList, location, flags); - break; - case SyntaxKind.EmptyStatement: - clone = createEmptyStatement(location, flags); - break; - case SyntaxKind.ExpressionStatement: - clone = createExpressionStatement((node).expression, location, flags); - break; - case SyntaxKind.IfStatement: - clone = createIfStatement((node).expression, (node).thenStatement, (node).elseStatement, location, flags); - break; - case SyntaxKind.DoStatement: - clone = createDoStatement((node).statement, (node).expression, location, flags); - break; - case SyntaxKind.WhileStatement: - clone = createWhileStatement((node).expression, (node).statement, location, flags); - break; - case SyntaxKind.ForStatement: - clone = createForStatement((node).initializer, (node).condition, (node).incrementor, (node).statement, location, flags); - break; - case SyntaxKind.ForInStatement: - clone = createForInStatement((node).initializer, (node).expression, (node).statement, location, flags); - break; - case SyntaxKind.ForOfStatement: - clone = createForOfStatement((node).initializer, (node).expression, (node).statement, location, flags); - break; - case SyntaxKind.ContinueStatement: - clone = createContinueStatement((node).label, location, flags); - break; - case SyntaxKind.BreakStatement: - clone = createBreakStatement((node).label, location, flags); - break; - case SyntaxKind.ReturnStatement: - clone = createReturnStatement((node).expression, location, flags); - break; - case SyntaxKind.WithStatement: - clone = createWithStatement((node).expression, (node).statement, location, flags); - break; - case SyntaxKind.SwitchStatement: - clone = createSwitchStatement((node).expression, (node).caseBlock, location, flags); - break; - case SyntaxKind.LabeledStatement: - clone = createLabeledStatement((node).label, (node).statement, location, flags); - break; - case SyntaxKind.ThrowStatement: - clone = createThrowStatement((node).expression, location, flags); - break; - case SyntaxKind.TryStatement: - clone = createTryStatement((node).tryBlock, (node).catchClause, (node).finallyBlock, location, flags); - break; - case SyntaxKind.DebuggerStatement: - clone = createDebuggerStatement(location, flags); - break; - case SyntaxKind.VariableDeclaration: - clone = createVariableDeclaration((node).name, (node).type, (node).initializer, location, flags); - break; - case SyntaxKind.VariableDeclarationList: - clone = createVariableDeclarationList((node).declarations, location, flags); - break; - case SyntaxKind.FunctionDeclaration: - clone = createFunctionDeclaration((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); - break; - case SyntaxKind.ClassDeclaration: - clone = createClassDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); - break; - case SyntaxKind.InterfaceDeclaration: - clone = createInterfaceDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); - break; - case SyntaxKind.TypeAliasDeclaration: - clone = createTypeAliasDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).type, location, flags); - break; - case SyntaxKind.EnumDeclaration: - clone = createEnumDeclaration((node).decorators, (node).modifiers, (node).name, (node).members, location, flags); - break; - case SyntaxKind.ModuleDeclaration: - clone = createModuleDeclaration((node).decorators, (node).modifiers, (node).name, (node).body, location, flags); - break; - case SyntaxKind.ModuleBlock: - clone = createModuleBlock((node).statements, location, flags); - break; - case SyntaxKind.CaseBlock: - clone = createCaseBlock((node).clauses, location, flags); - break; - case SyntaxKind.ImportEqualsDeclaration: - clone = createImportEqualsDeclaration((node).decorators, (node).modifiers, (node).name, (node).moduleReference, location, flags); - break; - case SyntaxKind.ImportDeclaration: - clone = createImportDeclaration((node).decorators, (node).modifiers, (node).importClause, (node).moduleSpecifier, location, flags); - break; - case SyntaxKind.ImportClause: - clone = createImportClause((node).name, (node).namedBindings, location, flags); - break; - case SyntaxKind.NamespaceImport: - clone = createNamespaceImport((node).name, location, flags); - break; - case SyntaxKind.NamedImports: - clone = createNamedImports((node).elements, location, flags); - break; - case SyntaxKind.ImportSpecifier: - clone = createImportSpecifier((node).propertyName, (node).name, location, flags); - break; - case SyntaxKind.ExportAssignment: - clone = createExportAssignment((node).decorators, (node).modifiers, (node).expression, location, flags); - break; - case SyntaxKind.ExportDeclaration: - clone = createExportDeclaration((node).decorators, (node).modifiers, (node).exportClause, (node).moduleSpecifier, location, flags); - break; - case SyntaxKind.NamedExports: - clone = createNamedExports((node).elements, location, flags); - break; - case SyntaxKind.ExportSpecifier: - clone = createExportSpecifier((node).propertyName, (node).name, location, flags); - break; - case SyntaxKind.MissingDeclaration: - clone = createMissingDeclaration((node).decorators, (node).modifiers, (node).questionToken, location, flags); - break; - case SyntaxKind.ExternalModuleReference: - clone = createExternalModuleReference((node).expression, location, flags); - break; - case SyntaxKind.JsxElement: - clone = createJsxElement((node).openingElement, (node).children, (node).closingElement, location, flags); - break; - case SyntaxKind.JsxSelfClosingElement: - clone = createJsxSelfClosingElement((node).tagName, (node).attributes, location, flags); - break; - case SyntaxKind.JsxOpeningElement: - clone = createJsxOpeningElement((node).tagName, (node).attributes, location, flags); - break; - case SyntaxKind.JsxText: - clone = createJsxText(location, flags); - break; - case SyntaxKind.JsxClosingElement: - clone = createJsxClosingElement((node).tagName, location, flags); - break; - case SyntaxKind.JsxAttribute: - clone = createJsxAttribute((node).name, (node).initializer, location, flags); - break; - case SyntaxKind.JsxSpreadAttribute: - clone = createJsxSpreadAttribute((node).expression, location, flags); - break; - case SyntaxKind.JsxExpression: - clone = createJsxExpression((node).expression, location, flags); - break; - case SyntaxKind.CaseClause: - clone = createCaseClause((node).expression, (node).statements, location, flags); - break; - case SyntaxKind.DefaultClause: - clone = createDefaultClause((node).statements, location, flags); - break; - case SyntaxKind.HeritageClause: - clone = createHeritageClause((node).token, (node).types, location, flags); - break; - case SyntaxKind.CatchClause: - clone = createCatchClause((node).variableDeclaration, (node).block, location, flags); - break; - case SyntaxKind.PropertyAssignment: - clone = createPropertyAssignment((node).name, (node).initializer, location, flags); - break; - case SyntaxKind.ShorthandPropertyAssignment: - clone = createShorthandPropertyAssignment((node).name, location, flags); - break; - case SyntaxKind.EnumMember: - clone = createEnumMember((node).name, (node).initializer, location, flags); - break; - case SyntaxKind.SourceFile: - clone = createSourceFileNode((node).statements, (node).endOfFileToken, (node).fileName, (node).text, (node).amdDependencies, (node).moduleName, (node).referencedFiles, (node).languageVariant, (node).renamedDependencies, (node).hasNoDefaultLib, (node).languageVersion, (node).externalModuleIndicator, (node).isDefaultLib, (node).identifiers, (node).parseDiagnostics, (node).bindDiagnostics, (node).lineMap, (node).classifiableNames, (node).resolvedModules, (node).imports, location, flags); - break; - case SyntaxKind.JSDocTypeExpression: - clone = createJSDocTypeExpression((node).type, location, flags); - break; - case SyntaxKind.JSDocAllType: - clone = createJSDocAllType(location, flags); - break; - case SyntaxKind.JSDocUnknownType: - clone = createJSDocUnknownType(location, flags); - break; - case SyntaxKind.JSDocArrayType: - clone = createJSDocArrayType((node).elementType, location, flags); - break; - case SyntaxKind.JSDocUnionType: - clone = createJSDocUnionType((node).types, location, flags); - break; - case SyntaxKind.JSDocTupleType: - clone = createJSDocTupleType((node).types, location, flags); - break; - case SyntaxKind.JSDocNullableType: - clone = createJSDocNullableType((node).type, location, flags); - break; - case SyntaxKind.JSDocNonNullableType: - clone = createJSDocNonNullableType((node).type, location, flags); - break; - case SyntaxKind.JSDocRecordType: - clone = createJSDocRecordType((node).members, location, flags); - break; - case SyntaxKind.JSDocRecordMember: - clone = createJSDocRecordMember((node).name, (node).type, location, flags); - break; - case SyntaxKind.JSDocTypeReference: - clone = createJSDocTypeReference((node).name, (node).typeArguments, location, flags); - break; - case SyntaxKind.JSDocOptionalType: - clone = createJSDocOptionalType((node).type, location, flags); - break; - case SyntaxKind.JSDocFunctionType: - clone = createJSDocFunctionType((node).parameters, (node).type, location, flags); - break; - case SyntaxKind.JSDocVariadicType: - clone = createJSDocVariadicType((node).type, location, flags); - break; - case SyntaxKind.JSDocConstructorType: - clone = createJSDocConstructorType((node).type, location, flags); - break; - case SyntaxKind.JSDocThisType: - clone = createJSDocThisType((node).type, location, flags); - break; - case SyntaxKind.JSDocComment: - clone = createJSDocComment((node).tags, location, flags); - break; - case SyntaxKind.JSDocTag: - clone = createJSDocTag((node).atToken, (node).tagName, location, flags); - break; - case SyntaxKind.JSDocParameterTag: - clone = createJSDocParameterTag((node).preParameterName, (node).typeExpression, (node).postParameterName, (node).atToken, (node).tagName, location, flags); - break; - case SyntaxKind.JSDocReturnTag: - clone = createJSDocReturnTag((node).typeExpression, (node).atToken, (node).tagName, location, flags); - break; - case SyntaxKind.JSDocTypeTag: - clone = createJSDocTypeTag((node).typeExpression, (node).atToken, (node).tagName, location, flags); - break; - case SyntaxKind.JSDocTemplateTag: - clone = createJSDocTemplateTag((node).typeParameters, (node).atToken, (node).tagName, location, flags); - break; - case SyntaxKind.RawExpression: - clone = createRawExpression((node).text, location, flags); - break; - case SyntaxKind.RawStatement: - clone = createRawStatement((node).text, location, flags); - break; - } - if (clone) { - clone.original = node; - return clone; - } - } - return node; - } export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node { if (node) { switch (node.kind) { @@ -3322,18 +2075,12 @@ namespace ts { return updateQualifiedName(node, transformer.visitNode((node).left, visitor, isEntityName), transformer.visitNode((node).right, visitor, isIdentifier)); case SyntaxKind.ComputedPropertyName: return updateComputedPropertyName(node, transformer.visitNode((node).expression, visitor, isExpressionNode)); - case SyntaxKind.TypeParameter: - return updateTypeParameter(node, transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNode((node).constraint, visitor, isTypeNodeNode), transformer.visitNode((node).expression, visitor, isExpressionNode)); case SyntaxKind.Parameter: return updateParameter(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isBindingPatternOrIdentifier), (node).questionToken, transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitNode((node).initializer, visitor, isExpressionNode)); case SyntaxKind.Decorator: return updateDecorator(node, transformer.visitNode((node).expression, visitor, isLeftHandSideExpression)); - case SyntaxKind.PropertySignature: - return updatePropertySignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNode((node).type, visitor, isTypeNodeNode)); case SyntaxKind.PropertyDeclaration: return updatePropertyDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitNode((node).initializer, visitor, isExpressionNode)); - case SyntaxKind.MethodSignature: - return updateMethodSignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); case SyntaxKind.MethodDeclaration: return updateMethodDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitFunctionBody((node).body, visitor)); case SyntaxKind.Constructor: @@ -3342,34 +2089,6 @@ namespace ts { return updateGetAccessor(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitFunctionBody((node).body, visitor)); case SyntaxKind.SetAccessor: return updateSetAccessor(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isPropertyName), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitFunctionBody((node).body, visitor)); - case SyntaxKind.CallSignature: - return updateCallSignature(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.ConstructSignature: - return updateConstructSignature(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.IndexSignature: - return updateIndexSignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.TypePredicate: - return updateTypePredicate(node, transformer.visitNode((node).parameterName, visitor, isIdentifier), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.TypeReference: - return updateTypeReference(node, transformer.visitNode((node).typeName, visitor, isEntityName), transformer.visitNodes((node).typeArguments, visitor, isTypeNodeNode)); - case SyntaxKind.FunctionType: - return updateFunctionType(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.ConstructorType: - return updateConstructorType(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); - case SyntaxKind.TypeQuery: - return updateTypeQuery(node, transformer.visitNode((node).exprName, visitor, isEntityName)); - case SyntaxKind.TypeLiteral: - return updateTypeLiteral(node, transformer.visitNodes((node).members, visitor, isTypeElement)); - case SyntaxKind.ArrayType: - return updateArrayType(node, transformer.visitNode((node).elementType, visitor, isTypeNodeNode)); - case SyntaxKind.TupleType: - return updateTupleType(node, transformer.visitNodes((node).elementTypes, visitor, isTypeNodeNode)); - case SyntaxKind.UnionType: - return updateUnionType(node, transformer.visitNodes((node).types, visitor, isTypeNodeNode)); - case SyntaxKind.IntersectionType: - return updateIntersectionType(node, transformer.visitNodes((node).types, visitor, isTypeNodeNode)); - case SyntaxKind.ParenthesizedType: - return updateParenthesizedType(node, transformer.visitNode((node).type, visitor, isTypeNodeNode)); case SyntaxKind.ObjectBindingPattern: return updateObjectBindingPattern(node, transformer.visitNodes((node).elements, visitor, isBindingElement)); case SyntaxKind.ArrayBindingPattern: @@ -3470,10 +2189,6 @@ namespace ts { return updateFunctionDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode), transformer.visitFunctionBody((node).body, visitor)); case SyntaxKind.ClassDeclaration: return updateClassDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).heritageClauses, visitor, isHeritageClause), transformer.visitNodes((node).members, visitor, isClassElement)); - case SyntaxKind.InterfaceDeclaration: - return updateInterfaceDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).heritageClauses, visitor, isHeritageClause), transformer.visitNodes((node).members, visitor, isTypeElement)); - case SyntaxKind.TypeAliasDeclaration: - return updateTypeAliasDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNode((node).type, visitor, isTypeNodeNode)); case SyntaxKind.EnumDeclaration: return updateEnumDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNode((node).name, visitor, isIdentifier), transformer.visitNodes((node).members, visitor, isEnumMember)); case SyntaxKind.ModuleDeclaration: @@ -3502,8 +2217,6 @@ namespace ts { return updateNamedExports(node, transformer.visitNodes((node).elements, visitor, isExportSpecifier)); case SyntaxKind.ExportSpecifier: return updateExportSpecifier(node, transformer.visitNode((node).propertyName, visitor, isIdentifier), transformer.visitNode((node).name, visitor, isIdentifier)); - case SyntaxKind.MissingDeclaration: - return updateMissingDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier)); case SyntaxKind.ExternalModuleReference: return updateExternalModuleReference(node, transformer.visitNode((node).expression, visitor, isExpressionNode)); case SyntaxKind.JsxElement: @@ -3536,46 +2249,6 @@ namespace ts { return updateEnumMember(node, transformer.visitNode((node).name, visitor, isDeclarationNameNode), transformer.visitNode((node).initializer, visitor, isExpressionNode)); case SyntaxKind.SourceFile: return updateSourceFileNode(node, transformer.visitNodes((node).statements, visitor, isStatementNode), (node).endOfFileToken); - case SyntaxKind.JSDocTypeExpression: - return updateJSDocTypeExpression(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocArrayType: - return updateJSDocArrayType(node, transformer.visitNode((node).elementType, visitor, isJSDocType)); - case SyntaxKind.JSDocUnionType: - return updateJSDocUnionType(node, transformer.visitNodes((node).types, visitor, isJSDocType)); - case SyntaxKind.JSDocTupleType: - return updateJSDocTupleType(node, transformer.visitNodes((node).types, visitor, isJSDocType)); - case SyntaxKind.JSDocNullableType: - return updateJSDocNullableType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocNonNullableType: - return updateJSDocNonNullableType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocRecordType: - return updateJSDocRecordType(node, transformer.visitNodes((node).members, visitor, isJSDocRecordMember)); - case SyntaxKind.JSDocRecordMember: - return updateJSDocRecordMember(node, transformer.visitNode((node).name, visitor, isIdentifierOrLiteralExpression), transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocTypeReference: - return updateJSDocTypeReference(node, transformer.visitNode((node).name, visitor, isEntityName), transformer.visitNodes((node).typeArguments, visitor, isJSDocType)); - case SyntaxKind.JSDocOptionalType: - return updateJSDocOptionalType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocFunctionType: - return updateJSDocFunctionType(node, transformer.visitNodes((node).parameters, visitor, isParameter), transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocVariadicType: - return updateJSDocVariadicType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocConstructorType: - return updateJSDocConstructorType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocThisType: - return updateJSDocThisType(node, transformer.visitNode((node).type, visitor, isJSDocType)); - case SyntaxKind.JSDocComment: - return updateJSDocComment(node, transformer.visitNodes((node).tags, visitor, isJSDocTag)); - case SyntaxKind.JSDocTag: - return updateJSDocTag(node, transformer.visitNode((node).tagName, visitor, isIdentifier)); - case SyntaxKind.JSDocParameterTag: - return updateJSDocParameterTag(node, transformer.visitNode((node).preParameterName, visitor, isIdentifier), transformer.visitNode((node).typeExpression, visitor, isJSDocTypeExpression), transformer.visitNode((node).postParameterName, visitor, isIdentifier), transformer.visitNode((node).tagName, visitor, isIdentifier)); - case SyntaxKind.JSDocReturnTag: - return updateJSDocReturnTag(node, transformer.visitNode((node).typeExpression, visitor, isJSDocTypeExpression), transformer.visitNode((node).tagName, visitor, isIdentifier)); - case SyntaxKind.JSDocTypeTag: - return updateJSDocTypeTag(node, transformer.visitNode((node).typeExpression, visitor, isJSDocTypeExpression), transformer.visitNode((node).tagName, visitor, isIdentifier)); - case SyntaxKind.JSDocTemplateTag: - return updateJSDocTemplateTag(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNode((node).tagName, visitor, isIdentifier)); } } return node; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 1f22ff0dad7..0b800d55fd0 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -152,7 +152,39 @@ namespace ts { } export function makeSynthesized(node: TNode): TNode { - return nodeIsSynthesized(node) ? node : cloneNode(node); + return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags); + } + + const cloneExcludedProperties: Map = { + "pos": true, + "end": true, + "flags": true, + "original": true, + "transformFlags": true, + "excludeTransformFlags": true, + "createParentNavigator": true + }; + + export function cloneNode(node: T, location?: TextRange, flags?: NodeFlags): T { + let clone = createNode(node.kind); + for (let id in node) { + if (hasProperty(cloneExcludedProperties, id)) { + continue; + } + + (clone)[id] = (node)[id]; + } + + if (location !== undefined) { + clone.pos = location.pos; + clone.end = location.end; + } + + if (flags !== undefined) { + clone.flags = flags; + } + + return clone; } const enum BinaryOperandSide { @@ -436,6 +468,10 @@ namespace ts { return createCallExpression2(createPropertyAccessExpression3(target, "apply"), [thisArg, _arguments], location, flags); } + export function createMathPowCall(left: Expression, right: Expression, location?: TextRange) { + return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Math"), "pow"), [left, right], location); + } + export function createExtendsHelperCall(name: Identifier) { return createCallExpression2(createIdentifier("__extends"), [name, createIdentifier("_super")]); } @@ -575,15 +611,6 @@ namespace ts { return createCallExpression2(createPropertyAccessExpression3(createIdentifier("React"), "__spread"), segments); } - export function createDefaultValueCheck(value: Expression, defaultValue: Expression, ensureIdentifier: (value: Expression, reuseIdentifierExpressions: boolean) => Expression, location?: TextRange, flags?: NodeFlags): Expression { - // The value expression will be evaluated twice, so for anything but a simple identifier - // we need to generate a temporary variable - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true); - - // === void 0 ? : - return createConditionalExpression2(createStrictEqualityExpression(value, createVoidZeroExpression()), defaultValue, value, location, flags); - } - export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange, flags?: NodeFlags): MemberExpression { return isIdentifier(memberName) ? createPropertyAccessExpression2(target, cloneNode(memberName), location, flags) : isComputedPropertyName(memberName) ? createElementAccessExpression2(target, cloneNode(memberName.expression), location, flags) diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 64ba2c0f285..75401a3eac5 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -4,7 +4,6 @@ /* @internal */ namespace ts { - const brackets = createBracketsMap(); const delimiters = createDelimiterMap(); export function printFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformations?: TransformationChain) { @@ -103,17 +102,20 @@ function __export(m) { } = transformer; let expressionSubstitution = transformer.getExpressionSubstitution(); + let bindingIdentifierSubstution = transformer.getBindingIdentifierSubstitution(); let compilerOptions = host.getCompilerOptions(); let languageVersion = getLanguageVersion(compilerOptions); let moduleKind = getModuleKind(compilerOptions); let diagnostics: Diagnostic[] = []; let currentSourceFile: SourceFile; let helpersEmitted: NodeCheckFlags; + let tempFlags: TempFlags; + let temporaryVariables: string[] = []; /** Emit a node */ let emit = emitNode; - let emitDetachedComments = function (node: Node) { }; + let emitDetachedComments = function (node: TextRange) { }; let emitLeadingComments = function (node: Node) { }; let emitTrailingComments = function (node: Node) { }; let emitTrailingCommentsOfPosition = function (pos: number) { }; @@ -176,11 +178,13 @@ function __export(m) { case SyntaxKind.FalseKeyword: case SyntaxKind.NullKeyword: case SyntaxKind.SuperKeyword: - case SyntaxKind.ThisKeyword: case SyntaxKind.TrueKeyword: case SyntaxKind.VoidKeyword: return writeTokenNode(node); + case SyntaxKind.ThisKeyword: + return emitThisKeyword(node); + // Contextual keywords case SyntaxKind.AnyKeyword: case SyntaxKind.BooleanKeyword: @@ -449,10 +453,6 @@ function __export(m) { return emitSourceFile(node); // JSDoc nodes (ignored) - // Raw nodes (deprecated) - case SyntaxKind.RawStatement: - case SyntaxKind.RawExpression: - return emitRaw(node); } } @@ -483,11 +483,17 @@ function __export(m) { // function emitIdentifier(node: Identifier) { + if (node.text === undefined) { + node.text + } if (isExpressionIdentifier(node)) { emitExpressionIdentifier(node); } + else if (tryEmitSubstitute(node, bindingIdentifierSubstution)) { + return; + } else if (nodeIsSynthesized(node)) { - write(node.text); + writeSynthesizedIdentifier(node); } else { writeTextOfNode(currentSourceFile, node); @@ -565,7 +571,7 @@ function __export(m) { writeLines(umdHelper); } else { - write(node.text); + writeSynthesizedIdentifier(node); } } else { @@ -573,6 +579,24 @@ function __export(m) { } } + function writeSynthesizedIdentifier(node: Identifier) { + let text = node.text || temporaryVariables[getOriginalNodeId(node)]; + if (text === undefined) { + text = temporaryVariables[getOriginalNodeId(node)] = makeTempVariableName(node.tempFlags); + } + + write(text); + } + + function emitThisKeyword(node: PrimaryExpression) { + if (tryEmitSubstitute(node, expressionSubstitution)) { + return; + } + else { + writeTokenNode(node); + } + } + // // Names // @@ -602,7 +626,7 @@ function __export(m) { function emitParameter(node: ParameterDeclaration) { emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); writeIfPresent(node.dotDotDotToken, "..."); emit(node.name); @@ -628,7 +652,7 @@ function __export(m) { function emitPropertySignature(node: PropertySignature) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); emit(node.name); writeIfPresent(node.questionToken, "?"); @@ -641,7 +665,7 @@ function __export(m) { function emitPropertyDeclaration(node: PropertyDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); emit(node.name); emitWithPrefix(": ", node.type); @@ -654,12 +678,12 @@ function __export(m) { function emitMethodSignature(node: MethodSignature) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); emit(node.name); writeIfPresent(node.questionToken, "?"); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.Parameters); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); emitWithPrefix(": ", node.type); write(";"); emitEnd(node); @@ -669,15 +693,11 @@ function __export(m) { function emitMethodDeclaration(node: MethodDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); writeIfPresent(node.asteriskToken, "*"); emit(node.name); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.Parameters); - emitWithPrefix(": ", node.type); - emit(node.body); - writeIfMissing(node.body, ";"); + emitSignatureAndBody(node); emitEnd(node); emitTrailingComments(node); } @@ -687,9 +707,8 @@ function __export(m) { emitStart(node); emitModifiers(node); write("constructor"); - emitList(node, node.parameters, ListFormat.Parameters); - emit(node.body); - writeIfMissing(node.body, ";"); + emitParameters(node, node.parameters); + emitFunctionBody(node, node.body); emitEnd(node); emitTrailingComments(node); } @@ -697,14 +716,11 @@ function __export(m) { function emitAccessorDeclaration(node: AccessorDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); emit(node.name); - emitList(node, node.parameters, ListFormat.Parameters); - emitWithPrefix(": ", node.type); - emit(node.body); - writeIfMissing(node.body, ";"); + emitSignatureAndBody(node); emitEnd(node); emitTrailingComments(node); } @@ -712,10 +728,10 @@ function __export(m) { function emitCallSignature(node: CallSignatureDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.Parameters); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); emitWithPrefix(": ", node.type); write(";"); emitEnd(node); @@ -725,11 +741,11 @@ function __export(m) { function emitConstructSignature(node: ConstructSignatureDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write("new "); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.Parameters); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); emitWithPrefix(": ", node.type); write(";"); emitEnd(node); @@ -739,9 +755,9 @@ function __export(m) { function emitIndexSignature(node: IndexSignatureDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); - emitList(node, node.parameters, ListFormat.IndexSignatureParameters); + emitParametersForIndexSignature(node, node.parameters); emitWithPrefix(": ", node.type); write(";"); emitEnd(node); @@ -763,14 +779,14 @@ function __export(m) { function emitTypeReference(node: TypeReferenceNode) { emitStart(node); emit(node.typeName); - emitList(node, node.typeArguments, ListFormat.TypeArguments); + emitTypeArguments(node, node.typeArguments); emitEnd(node); } function emitFunctionType(node: FunctionTypeNode) { emitStart(node); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.ArrowParameters); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); write(" => "); emit(node.type); emitEnd(node); @@ -779,8 +795,8 @@ function __export(m) { function emitConstructorType(node: ConstructorTypeNode) { emitStart(node); write("new "); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.ArrowParameters); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); write(" => "); emit(node.type); emitEnd(node); @@ -795,7 +811,9 @@ function __export(m) { function emitTypeLiteral(node: TypeLiteralNode) { emitStart(node); - emitList(node, node.members, ListFormat.TypeElements); + write("{"); + emitList(node, node.members, ListFormat.MultiLine | ListFormat.Indented); + write("}"); emitEnd(node); } @@ -808,19 +826,21 @@ function __export(m) { function emitTupleType(node: TupleTypeNode) { emitStart(node); - emitList(node, node.elementTypes, ListFormat.TupleTypeElementTypes); + write("["); + emitList(node, node.elementTypes, ListFormat.CommaDelimited | ListFormat.SingleLine | ListFormat.Indented); + write("]"); emitEnd(node); } function emitUnionType(node: UnionTypeNode) { emitStart(node); - emitList(node, node.types, ListFormat.UnionTypeConstituents) + emitList(node, node.types, ListFormat.BarDelimited | ListFormat.SingleLine) emitEnd(node); } function emitIntersectionType(node: IntersectionTypeNode) { emitStart(node); - emitList(node, node.types, ListFormat.IntersectionTypeConstituents); + emitList(node, node.types, ListFormat.AmpersandDelimited | ListFormat.SingleLine); emitEnd(node); } @@ -835,11 +855,27 @@ function __export(m) { // function emitObjectBindingPattern(node: ObjectBindingPattern) { - emitList(node, node.elements, ListFormat.ObjectBindingPatternElements); + let elements = node.elements; + if (elements.length === 0) { + write("{}"); + } + else { + write("{"); + emitList(node, elements, ListFormat.SingleLine | ListFormat.AllowTrailingComma | ListFormat.SpaceBetweenBraces); + write("}"); + } } function emitArrayBindingPattern(node: ArrayBindingPattern) { - emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); + let elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + write("["); + emitList(node, node.elements, ListFormat.SingleLine | ListFormat.AllowTrailingComma); + write("]"); + } } function emitBindingElement(node: BindingElement) { @@ -854,13 +890,30 @@ function __export(m) { // function emitArrayLiteralExpression(node: ArrayLiteralExpression) { - emitList(node, node.elements, ListFormat.ArrayLiteralExpressionElements); + let elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + const preferNewLine = node.flags & NodeFlags.MultiLine ? ListFormat.PreferNewLine : ListFormat.None; + write("["); + emitList(node, elements, ListFormat.PreserveLines | ListFormat.CommaDelimited | ListFormat.AllowTrailingComma | ListFormat.Indented | preferNewLine); + write("]"); + } } function emitObjectLiteralExpression(node: ObjectLiteralExpression) { - emitList(node, node.properties, languageVersion < ScriptTarget.ES5 - ? ListFormat.ObjectLiteralExpressionProperties - : ListFormat.ObjectLiteralExpressionPropertiesForES5AndLater); + let properties = node.properties; + if (properties.length === 0) { + write("{}"); + } + else { + const preferNewLine = node.flags & NodeFlags.MultiLine ? ListFormat.PreferNewLine : ListFormat.None; + const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; + write("{"); + emitList(node, properties, ListFormat.PreserveLines | ListFormat.CommaDelimited | ListFormat.SpaceBetweenBraces | ListFormat.Indented | allowTrailingComma | preferNewLine); + write("}"); + } } function emitPropertyAccessExpression(node: PropertyAccessExpression) { @@ -910,13 +963,19 @@ function __export(m) { function emitCallExpression(node: CallExpression) { emit(node.expression); - emitList(node, node.arguments, ListFormat.CallExpressionArguments); + write("("); + emitList(node, node.arguments, ListFormat.CommaDelimited | ListFormat.SingleLine); + write(")"); } function emitNewExpression(node: NewExpression) { write("new "); emit(node.expression); - emitList(node, node.arguments, ListFormat.NewExpressionArguments); + if (node.arguments) { + write("("); + emitList(node, node.arguments, ListFormat.CommaDelimited | ListFormat.SingleLine); + write(")"); + } } function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -925,9 +984,12 @@ function __export(m) { } function emitTypeAssertionExpression(node: TypeAssertion) { - write("<"); - emit(node.type); - write(">"); + if (node.type) { + write("<"); + emit(node.type); + write(">"); + } + emit(node.expression); } @@ -942,14 +1004,32 @@ function __export(m) { } function emitArrowFunction(node: ArrowFunction) { + let savedTempFlags = tempFlags; + tempFlags = 0; emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.ArrowParameters); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); emitWithPrefix(": ", node.type); - emit(node.body); + write(" =>"); + emitConciseBody(node, node.body); emitEnd(node); + tempFlags = savedTempFlags; + } + + function emitConciseBody(parentNode: Node, body: ConciseBody) { + if (isBlock(body)) { + let wasPushed = tryPushNode(body); + emitBlockFunctionBody(parentNode, body); + if (wasPushed) { + popNode(); + } + } + else { + write(" "); + emit(body); + } } function emitDeleteExpression(node: DeleteExpression) { @@ -1040,14 +1120,14 @@ function __export(m) { increaseIndentIf(indentBeforeColon, " "); write(":"); - increaseIndentIf(indentAfterColon); + increaseIndentIf(indentAfterColon, " "); emit(node.whenFalse); decreaseIndentIf(indentBeforeColon, indentAfterColon); } function emitTemplateExpression(node: TemplateExpression) { emit(node.head); - emitList(node, node.templateSpans, ListFormat.TemplateExpressionTemplateSpans); + emitList(node, node.templateSpans, ListFormat.SingleLine); } function emitYieldExpression(node: YieldExpression) { @@ -1067,14 +1147,16 @@ function __export(m) { function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { emitStart(node); emit(node.expression); - emitList(node, node.typeArguments, ListFormat.TypeArguments); + emitTypeArguments(node, node.typeArguments); emitEnd(node); } function emitAsExpression(node: AsExpression) { emit(node.expression); - write(" as "); - emit(node.type); + if (node.type) { + write(" as "); + emit(node.type); + } } // @@ -1090,12 +1172,25 @@ function __export(m) { // Statements // - function emitBlock(node: Block, isFunctionBody?: boolean) { - emitLeadingComments(node); - emitStart(node); - emitList(node, node.statements, addHelpers(node, isFunctionBody ? ListFormat.FunctionBodyStatements : ListFormat.BlockStatements)); - emitEnd(node); - emitTrailingComments(node); + function emitBlock(node: Block, format?: ListFormat) { + if (isSingleLineEmptyBlock(node)) { + write("{ }"); + } + else { + emitStart(node); + write("{"); + scopeEmitStart(getParentNode()); + if (node.flags & NodeFlags.SingleLine) { + emitList(node, node.statements, addHelpers(node, ListFormat.SpaceBetweenBraces | ListFormat.SingleLine | format)); + } + else { + emitList(node, node.statements, addHelpers(node, ListFormat.Indented | ListFormat.MultiLine | format)); + } + + scopeEmitEnd(); + write("}"); + emitEnd(node); + } } function emitVariableStatement(node: VariableStatement) { @@ -1121,7 +1216,13 @@ function __export(m) { if (node.elseStatement) { writeLine(); write("else"); - emitEmbeddedStatement(node.elseStatement); + if (isIfStatement(node.elseStatement)) { + write(" "); + emit(node.elseStatement); + } + else { + emitEmbeddedStatement(node.elseStatement); + } } } @@ -1210,8 +1311,8 @@ function __export(m) { function emitLabeledStatement(node: LabeledStatement) { emit(node.label); - write(":"); - emitEmbeddedStatement(node.statement); + write(": "); + emit(node.statement); } function emitThrowStatement(node: ThrowStatement) { @@ -1246,7 +1347,7 @@ function __export(m) { function emitVariableDeclarationList(node: VariableDeclarationList) { write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); - emitList(node, node.declarations, ListFormat.VariableDeclarations); + emitList(node, node.declarations, ListFormat.CommaDelimited | ListFormat.SingleLine); } function emitFunctionDeclaration(node: FunctionDeclaration) { @@ -1256,23 +1357,31 @@ function __export(m) { function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write(node.asteriskToken ? "function* " : "function "); emit(node.name); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.parameters, ListFormat.Parameters); - emitWithPrefix(": ", node.type); - emitFunctionBody(node.body); + emitSignatureAndBody(node); emitEnd(node); emitTrailingComments(node); } - function emitFunctionBody(node: Block) { - if (node) { - write(" "); - let wasPushed = tryPushNode(node); - emitBlock(node, /*isFunctionBody*/ true); + function emitSignatureAndBody(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration) { + let savedTempFlags = tempFlags; + tempFlags = 0; + + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + emitFunctionBody(node, node.body); + + tempFlags = savedTempFlags; + } + + function emitFunctionBody(parentNode: Node, body: FunctionBody) { + if (body) { + let wasPushed = tryPushNode(body); + emitBlockFunctionBody(parentNode, body); if (wasPushed) { popNode(); } @@ -1282,6 +1391,46 @@ function __export(m) { } } + function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) { + let originalNode = getOriginalNode(parentNode); + if (isFunctionLike(originalNode) && !nodeIsSynthesized(originalNode) && rangeEndIsOnSameLineAsRangeStart(originalNode.body, originalNode.body)) { + for (let statement of body.statements) { + if (synthesizedNodeStartsOnNewLine(statement)) { + return false; + } + } + + if (isArrowFunction(originalNode) && !rangeEndIsOnSameLineAsRangeStart(originalNode.equalsGreaterThanToken, originalNode.body)) { + return false; + } + + return true; + } + + return false; + } + + function emitBlockFunctionBody(parentNode: Node, body: Block) { + let statements = body.statements; + write(" {"); + scopeEmitStart(parentNode); + + // Emit all the prologue directives (like "use strict"). + increaseIndent(); + let statementOffset = emitPrologueDirectives(statements, /*startWithNewLine*/ true); + decreaseIndent(); + + if (statementOffset === 0 && shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)) { + emitList(body, statements, addHelpers(body, ListFormat.SingleLine | ListFormat.SpaceBetweenBraces | ListFormat.LexicalEnvironment)); + } + else { + emitList(body, statements, addHelpers(body, ListFormat.MultiLine | ListFormat.Indented | ListFormat.LexicalEnvironment), statementOffset); + } + + scopeEmitEnd(); + write("}"); + } + function emitClassDeclaration(node: ClassDeclaration) { emitClassDeclarationOrExpression(node); } @@ -1289,14 +1438,24 @@ function __export(m) { function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write("class"); emitWithPrefix(" ", node.name); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.heritageClauses, ListFormat.HeritageClauses); - write(" "); - emitList(node, node.members, ListFormat.ClassMembers); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.SingleLine); + + let savedTempFlags = tempFlags; + tempFlags = 0; + + write(" {"); + scopeEmitStart(node); + emitList(node, node.members, ListFormat.Indented | ListFormat.MultiLine); + scopeEmitEnd(); + write("}"); + + tempFlags = savedTempFlags; + emitEnd(node); emitTrailingComments(node); } @@ -1304,14 +1463,15 @@ function __export(m) { function emitInterfaceDeclaration(node: InterfaceDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write("interface "); emit(node.name); - emitList(node, node.typeParameters, ListFormat.TypeParameters); - emitList(node, node.heritageClauses, ListFormat.HeritageClauses); - write(" "); - emitList(node, node.members, ListFormat.TypeElements); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.SingleLine); + write(" {"); + emitList(node, node.members, ListFormat.Indented | ListFormat.MultiLine); + write("}"); emitEnd(node); emitTrailingComments(node); } @@ -1319,11 +1479,11 @@ function __export(m) { function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { emitLeadingComments(node); emitStart(node); - emitList(node, node.decorators, ListFormat.Decorators); + emitDecorators(node, node.decorators); emitModifiers(node); write("type "); emit(node.name); - emitList(node, node.typeParameters, ListFormat.TypeParameters); + emitTypeParameters(node, node.typeParameters); write(" = "); emit(node.type); write(";"); @@ -1337,8 +1497,16 @@ function __export(m) { emitModifiers(node); write("enum "); emit(node.name); - write(" "); - emitList(node, node.members, ListFormat.EnumMembers); + + let savedTempFlags = tempFlags; + tempFlags = 0; + + write(" {"); + emitList(node, node.members, ListFormat.CommaDelimited | ListFormat.Indented | ListFormat.MultiLine); + write("}"); + + tempFlags = savedTempFlags; + emitEnd(node); emitTrailingComments(node); } @@ -1364,11 +1532,18 @@ function __export(m) { } function emitModuleBlock(node: ModuleBlock) { - emitList(node, node.statements, ListFormat.ModuleBlockStatements); + let savedTempFlags = tempFlags; + tempFlags = 0; + + emitBlock(node, ListFormat.LexicalEnvironment); + + tempFlags = savedTempFlags; } function emitCaseBlock(node: CaseBlock) { - emitList(node, node.clauses, ListFormat.CaseBlockClauses); + write("{"); + emitList(node, node.clauses, ListFormat.Indented | ListFormat.MultiLine); + write("}"); } function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { @@ -1459,7 +1634,9 @@ function __export(m) { function emitNamedImportsOrExports(node: NamedImportsOrExports) { emitStart(node); - emitList(node, node.elements, ListFormat.ImportOrExportSpecifiers); + write("{ "); + emitList(node, node.elements, ListFormat.CommaDelimited | ListFormat.AllowTrailingComma | ListFormat.SingleLine); + write(" }"); emitEnd(node); } @@ -1492,7 +1669,7 @@ function __export(m) { function emitJsxElement(node: JsxElement) { emit(node.openingElement); - emitList(node, node.children, ListFormat.JsxElementChildren); + emitList(node, node.children, ListFormat.SingleLine); emit(node.closingElement); } @@ -1500,7 +1677,7 @@ function __export(m) { write("<"); emit(node.tagName); write(" "); - emitList(node, node.attributes, ListFormat.JsxAttributes); + emitList(node, node.attributes, ListFormat.SingleLine); write("/>"); } @@ -1508,7 +1685,7 @@ function __export(m) { write("<"); emit(node.tagName); writeIfAny(node.attributes, " "); - emitList(node, node.attributes, ListFormat.JsxAttributes); + emitList(node, node.attributes, ListFormat.SingleLine); write(">"); } @@ -1547,19 +1724,29 @@ function __export(m) { write("case "); emit(node.expression); write(":"); - emitList(node, node.statements, ListFormat.CaseOrDefaultClauseStatements); + emitCaseOrDefaultClauseStatements(node, node.statements); } function emitDefaultClause(node: DefaultClause) { write("default:"); - emitList(node, node.statements, ListFormat.CaseOrDefaultClauseStatements); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + + function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray) { + if (statements.length === 1 && rangeStartPositionsAreOnSameLine(parentNode, statements[0])) { + write(" "); + emit(statements[0]); + } + else { + emitList(parentNode, statements, ListFormat.Indented | ListFormat.MultiLine); + } } function emitHeritageClause(node: HeritageClause) { emitStart(node); writeToken(node.token); write(" "); - emitList(node, node.types, ListFormat.HeritageClauseTypes); + emitList(node, node.types, ListFormat.CommaDelimited | ListFormat.SingleLine); emitEnd(node); } @@ -1611,49 +1798,59 @@ function __export(m) { // function emitSourceFile(node: SourceFile) { + let savedTempFlags = tempFlags; + tempFlags = 0; currentSourceFile = node; + writeLine(); emitShebang(); emitDetachedComments(node); - emitList(node, node.statements, addHelpers(node, ListFormat.SourceFileStatements)); + + let statements = node.statements; + let statementOffset = emitPrologueDirectives(statements); + emitList(node, statements, addHelpers(node, ListFormat.MultiLine), statementOffset); + currentSourceFile = undefined; + tempFlags = savedTempFlags; } - function emitLexicalEnvironment(node: Statement) { - writeLine(); + function emitLexicalEnvironmentOnNewLine(node: Statement) { + emitLexicalEnvironment(node, /*newLine*/ true); + } + + function emitLexicalEnvironment(node: Statement, newLine?: boolean) { + if (newLine) { + writeLine(); + } + else { + write(" "); + } + emit(node); } - function emitPrologueDirectives(statements: Node[], start?: number, count?: number) { - if (start === undefined) { - start = 0; - } - - if (count === undefined) { - count = statements.length - start; - } - - for (let i = 0; i < count; i++) { - let offset = start + i; - if (isPrologueDirective(statements[offset])) { - if (i > 0) { + function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean) { + for (let i = 0; i < statements.length; i++) { + if (isPrologueDirective(statements[i])) { + if (startWithNewLine || i > 0) { writeLine(); } - - emit(statements[offset]); + emit(statements[i]); } else { + // return index of the first non prologue directive return i; } } - return count; + return statements.length; } function emitEmitHelpers(node: SourceFile) { let flags = resolver.getNodeCheckFlags(node); // Only emit helpers if the user did not say otherwise. + let previousHelpersEmitted = helpersEmitted; if (!compilerOptions.noEmitHelpers) { if (shouldEmitHelper(NodeCheckFlags.EmitExtends, flags) && languageVersion < ScriptTarget.ES6) { writeLines(extendsHelper); @@ -1678,6 +1875,10 @@ function __export(m) { writeLines(awaiterHelper); helpersEmitted |= NodeCheckFlags.EmitAwaiter; } + + if (helpersEmitted !== previousHelpersEmitted) { + writeLine(); + } } } @@ -1690,10 +1891,6 @@ function __export(m) { && !(helpersEmitted && helper); } - function emitRaw(node: RawStatement | RawExpression) { - writeLines(node.text); - } - function writeLines(text: string): void { let lines = text.split(/\r\n|\r|\n/g); for (let i = 0; i < lines.length; ++i) { @@ -1807,85 +2004,90 @@ function __export(m) { } } - function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { - if (!children && format & ListFormat.Optional) { - return; + function emitDecorators(parentNode: Node, decorators: NodeArray) { + if (decorators && decorators.length) { + emitList(parentNode, decorators, ListFormat.MultiLine); } + } - let containingRange: TextRange = format & ListFormat.Fragment ? children : parentNode; + function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { + if (typeArguments && typeArguments.length > 0) { + write("<"); + emitList(parentNode, typeArguments, ListFormat.CommaDelimited | ListFormat.SingleLine | ListFormat.Indented) + write(">"); + } + } - // Shortcut for an empty list. + function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { + if (typeParameters && typeParameters.length > 0) { + write("<"); + emitList(parentNode, typeParameters, ListFormat.CommaDelimited | ListFormat.SingleLine | ListFormat.Indented) + write(">"); + } + } + + function emitParameters(parentNode: Node, parameters: NodeArray) { + write("("); + emitList(parentNode, parameters, ListFormat.CommaDelimited | ListFormat.SingleLine | ListFormat.Indented); + write(")"); + } + + function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { + if (parameters && + parameters.length === 1 && + parameters[0].type === undefined && + parameters[0].pos === parentNode.pos) { + emit(parameters[0]); + } + else { + emitParameters(parentNode, parameters); + } + } + + function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { + write("["); + emitList(parentNode, parameters, ListFormat.CommaDelimited | ListFormat.SingleLine | ListFormat.Indented); + write("]"); + } + + function emitTypeElements(parentNode: Node, elements: NodeArray) { + emitList(parentNode, elements, ListFormat.MultiLine | ListFormat.Indented); + } + + function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start: number = 0, count: number = children ? children.length - start : 0) { if (!children || children.length === 0 || start >= children.length || count === 0) { - // If the list is bracketed, emit the brackets and any interceeding whitespace. - if (format & ListFormat.BracketsMask) { - write(getBracket(format, ListFormat.LeadingBracketOffset)); - if (containingRange && !positionsAreOnSameLine(containingRange.pos, containingRange.end)) { - writeLine(); - } - else if (format & ListFormat.Whitespace) { - write(" "); - } - write(getBracket(format, ListFormat.TrailingBracketOffset)); + // Write a line terminator if the parent node was multi-line + if (format & ListFormat.MultiLine) { + writeLine(); } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + return; } - if (start === undefined) { - start = 0; - } - - if (count === undefined) { - count = children.length - start; - } - let previousSibling: Node; - let firstChild = start < children.length ? children[start] : undefined; - let lastChild = start + count <= children.length ? children[start + count - 1] : undefined; - - // Shortcut for a simple arrow function. - if (format & ListFormat.Arrow && - children.length === 1 && - isParameter(firstChild) && - firstChild.type === undefined && - firstChild.pos === parentNode.pos) { - emit(firstChild); - return; - } - - // Write the leading bracket. - write(getBracket(format, ListFormat.LeadingBracketOffset)); - - // Start the new scope, if requested. - if (format & ListFormat.Scoped) { - scopeEmitStart(parentNode); - } // Write the opening line terminator or leading whitespace. - if (shouldWriteLeadingLineTerminator(containingRange, firstChild, format)) { + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { writeLine(); } - else if (format & ListFormat.LeadingWhitespace) { + else if (format & ListFormat.SpaceBetweenBraces) { write(" "); } // Increase the indent, if requested. - let indented = format & ListFormat.Indented; - if (indented) { + if (format & ListFormat.Indented) { increaseIndent(); } + // Start the lexical environment, if requested. if (format & ListFormat.LexicalEnvironment) { startLexicalEnvironment(); } - // Print prologue directives, if needed - if (format & ListFormat.MustEmitPrologueDirectivesFirst) { - let directivesWritten = emitPrologueDirectives(children, start, count); - start += directivesWritten; - count -= directivesWritten; - } - - // Print the emit helpers, if requested. + // Print emit helpers, if requested. if (format & ListFormat.PrintEmitHelpers) { emitEmitHelpers(currentSourceFile); } @@ -1896,7 +2098,6 @@ function __export(m) { } // Emit each child. - let canBeDedented = indented && canHaveDedentedChildren(parentNode); let delimiter = getDelimiter(format); for (let i = 0; i < count; i++) { let child = children[start + i]; @@ -1914,19 +2115,9 @@ function __export(m) { } } - // For cleaner emit, decrease the indent level for function expressions in an argument list - let dedented = canBeDedented && shouldDedentChild(child); - if (dedented) { - decreaseIndent(); - } - // Emit this child. emit(child); - if (dedented) { - increaseIndent(); - } - previousSibling = child; } @@ -1937,38 +2128,22 @@ function __export(m) { } if (format & ListFormat.LexicalEnvironment) { - endLexicalEnvironment(emitLexicalEnvironment); + let isSingleLine = (format & (ListFormat.MultiLine | ListFormat.PreserveLines)) === 0; + endLexicalEnvironment(isSingleLine ? emitLexicalEnvironment : emitLexicalEnvironmentOnNewLine); } // Decrease the indent, if requested. - if (indented) { + if (format & ListFormat.Indented) { decreaseIndent(); } // Write the closing line terminator or closing whitespace. - if (shouldWriteClosingLineTerminator(containingRange, lastChild, format)) { + if (shouldWriteClosingLineTerminator(parentNode, children, format)) { writeLine(); } - else if (format & ListFormat.TrailingWhitespace && (previousSibling || hasTrailingComma)) { + else if (format & ListFormat.SpaceBetweenBraces) { write(" "); } - - // End the scope, if requested. - if (format & ListFormat.Scoped) { - scopeEmitEnd(); - } - - // Write the trailing bracket. - write(getBracket(format, ListFormat.TrailingBracketOffset)); - } - - function canHaveDedentedChildren(node: Node) { - return isCallExpression(node) || isNewExpression(node) || isVariableDeclarationList(node); - } - - function shouldDedentChild(node: Node): boolean { - return isFunctionExpression(node) || isArrowFunction(node) || isObjectLiteralExpression(node) || isArrayLiteralExpression(node) || - (isVariableDeclaration(node) && shouldDedentChild(node.initializer)); } function writeIfAny(nodes: NodeArray, text: string) { @@ -2022,42 +2197,73 @@ function __export(m) { } } - function shouldWriteLeadingLineTerminator(containingRange: TextRange, firstChild: Node, format?: ListFormat) { - if (containingRange === undefined) { - return false; + function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; } - else if (firstChild === undefined) { - return !positionsAreOnSameLine(getStartPos(containingRange), getEndPos(containingRange)); - } - else if (positionIsSynthesized(containingRange.pos) || nodeIsSynthesized(firstChild)) { - return synthesizedNodeStartsOnNewLine(firstChild, format); + else if (format & ListFormat.PreserveLines) { + if (parentNode.flags & NodeFlags.MultiLine) { + return true; + } + + let firstChild = firstOrUndefined(children); + if (firstChild === undefined) { + return !positionsAreOnSameLine(getStartPos(parentNode), parentNode.end); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { + return synthesizedNodeStartsOnNewLine(firstChild, format); + } + else { + return !rangeStartPositionsAreOnSameLine(parentNode, firstChild); + } } else { - return !rangeStartPositionsAreOnSameLine(containingRange, firstChild); + return false; } } - function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format?: ListFormat) { - if (previousNode === undefined || nextNode === undefined) { - return false; + function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; } - else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { - return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + else if (format & ListFormat.PreserveLines) { + if (previousNode === undefined || nextNode === undefined) { + return false; + } + else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { + return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + } + else { + return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode); + } } else { - return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode); + return false; } } - function shouldWriteClosingLineTerminator(containingRange: TextRange, lastChild: Node, format?: ListFormat) { - if (lastChild === undefined) { - return false; + function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; } - else if (positionIsSynthesized(containingRange.pos) || nodeIsSynthesized(lastChild)) { - return synthesizedNodeStartsOnNewLine(lastChild, format); + else if (format & ListFormat.PreserveLines) { + if (parentNode.flags & NodeFlags.MultiLine) { + return true; + } + + let lastChild = lastOrUndefined(children); + if (lastChild === undefined) { + return !positionsAreOnSameLine(getStartPos(parentNode), parentNode.end); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { + return synthesizedNodeStartsOnNewLine(lastChild, format); + } + else { + return !rangeEndPositionsAreOnSameLine(parentNode, lastChild); + } } else { - return !rangeEndPositionsAreOnSameLine(containingRange, lastChild); + return false; } } @@ -2078,11 +2284,11 @@ function __export(m) { } function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange) { - return positionsAreOnSameLine(getEndPos(range1), getEndPos(range2)); + return positionsAreOnSameLine(range1.end, range2.end); } function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange) { - return positionsAreOnSameLine(getEndPos(range1), getStartPos(range2)); + return positionsAreOnSameLine(range1.end, getStartPos(range2)); } function positionsAreOnSameLine(pos1: number, pos2: number) { @@ -2091,11 +2297,7 @@ function __export(m) { } function getStartPos(range: TextRange) { - return skipTrivia(currentSourceFile.text, range.pos); - } - - function getEndPos(range: TextRange) { - return range.end; + return range.pos === -1 ? -1 : skipTrivia(currentSourceFile.text, range.pos); } function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { @@ -2141,6 +2343,40 @@ function __export(m) { } return format; } + + function isSingleLineEmptyBlock(block: Block) { + return (block.flags & NodeFlags.MultiLine) === 0 && + block.statements.length === 0 && + rangeEndIsOnSameLineAsRangeStart(block, block); + } + + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ + function makeTempVariableName(flags: TempFlags): string { + if (flags && !(tempFlags & flags)) { + let name = flags === TempFlags._i ? "_i" : "_n"; + if (transformer.isUniqueName(name)) { + tempFlags |= flags; + return name; + } + } + while (true) { + let count = tempFlags & TempFlags.CountMask; + tempFlags++; + // Skip over 'i' and 'n' + if (count !== 8 && count !== 13) { + let name = count < 26 + ? "_" + String.fromCharCode(CharacterCodes.a + count) + : "_" + (count - 26); + if (transformer.isUniqueName(name)) { + return name; + } + } + } + } } } @@ -2157,95 +2393,30 @@ function __export(m) { return delimiters[format & ListFormat.DelimitersMask]; } - function createBracketsMap() { - let brackets: string[] = []; - brackets[ListFormat.None] = ""; - brackets[ListFormat.Parentheses << ListFormat.LeadingBracketOffset] = "("; - brackets[ListFormat.Parentheses << ListFormat.TrailingBracketOffset] = ")"; - brackets[ListFormat.SquareBrackets << ListFormat.LeadingBracketOffset] = "["; - brackets[ListFormat.SquareBrackets << ListFormat.TrailingBracketOffset] = "]"; - brackets[ListFormat.CurlyBrackets << ListFormat.LeadingBracketOffset] = "{"; - brackets[ListFormat.CurlyBrackets << ListFormat.TrailingBracketOffset] = "}"; - brackets[ListFormat.AngleBrackets << ListFormat.LeadingBracketOffset] = "<"; - brackets[ListFormat.AngleBrackets << ListFormat.TrailingBracketOffset] = ">"; - return brackets; - } - - function getBracket(format: ListFormat, offset: number) { - return brackets[(format & ListFormat.BracketsMask) << offset]; - } - const enum ListFormat { None = 0, - // Brackets - Parentheses = 1 << 0, // The list is surrounded with parentheses ("(", ")"). - SquareBrackets = 1 << 1, // The list is surrounded with brackets ("[", "]"). - CurlyBrackets = 1 << 2, // The list is surrounded with braces ("{", "}"). - AngleBrackets = 1 << 3, // The list is surrounded with angle-brackets ("<", ">"). - - LeadingBracketOffset = 0, // Left-shift offset for a leading bracket. - TrailingBracketOffset = 4, // Left-shift offset for a trailing bracket. - BracketsMask = Parentheses | SquareBrackets | CurlyBrackets | AngleBrackets, + // Line separators + SingleLine = 1 << 0, // Prints the list on a single line (default). + MultiLine = 1 << 1, // Prints the list on multiple lines. + PreserveLines = 1 << 2, // Prints the list using line preservation if possible. // Delimiters - BarDelimited = 1 << 4, // Each list item is space-and-bar (" |") delimited. - AmpersandDelimited = 1 << 5, // Each list item is space-and-ampersand (" &") delimited. - CommaDelimited = 1 << 6, // Each list item is comma (",") delimited. - AllowTrailingComma = 1 << 7, // Write a trailing comma (",") if present. + NotDelimited = 0, // There is no delimiter between list items (default). + BarDelimited = 1 << 3, // Each list item is space-and-bar (" |") delimited. + AmpersandDelimited = 1 << 4, // Each list item is space-and-ampersand (" &") delimited. + CommaDelimited = 1 << 5, // Each list item is comma (",") delimited. + AllowTrailingComma = 1 << 6, // Write a trailing comma (",") if present. DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, // Whitespace - Indented = 1 << 8, // The list should be indented. - LeadingWhitespace = 1 << 9, // Write a leading space (" ") before the first element if not indented. - TrailingWhitespace = 1 << 10, // Write a trailing space (" ") after the last element if not indented. - Whitespace = LeadingWhitespace | TrailingWhitespace, + Indented = 1 << 7, // The list should be indented. + SpaceBetweenBraces = 1 << 8, // Inserts a space after the opening brace and before the closing brace. // Other - Optional = 1 << 11, // Skip writing brackets (if any) for an empty or missing list. - Scoped = 1 << 12, // The list starts a new scope (for Source Maps). - Arrow = 1 << 13, // The list is a parameter list for an arrow function. - Fragment = 1 << 14, // The list is a fragment of the node. Line terminators should be based on the node array positions. - PreferNewLine = 1 << 15, // Prefer adding LineTerminators between synthesized nodes. - PrintEmitHelpers = 1 << 16, // Emit any emit helpers along with the list - PrintExportStar = 1 << 17, // Emit the __export helper for "export *" - LexicalEnvironment = 1 << 18, // Marks a lexical environment - - // List formats - Decorators = Indented | TrailingWhitespace | Fragment, - TypeParameters = AngleBrackets | CommaDelimited | Indented | Optional | Fragment, - Parameters = Parentheses | CommaDelimited | Indented | Fragment, - ArrowParameters = Parameters | Arrow, - IndexSignatureParameters = SquareBrackets | CommaDelimited | Indented | Fragment, - TypeArguments = AngleBrackets | CommaDelimited | Indented | Optional | Fragment, - TypeElements = CurlyBrackets | Indented | Whitespace | PreferNewLine, - TupleTypeElementTypes = SquareBrackets | CommaDelimited | Indented, - UnionTypeConstituents = BarDelimited | Indented, - IntersectionTypeConstituents = AmpersandDelimited | Indented, - ObjectBindingPatternElements = CurlyBrackets | CommaDelimited | AllowTrailingComma | Indented | LeadingWhitespace | TrailingWhitespace | PreferNewLine, - ArrayBindingPatternElements = SquareBrackets | CommaDelimited | AllowTrailingComma | Indented, - ArrayLiteralExpressionElements = SquareBrackets | CommaDelimited | AllowTrailingComma | Indented, - ObjectLiteralExpressionProperties = CurlyBrackets | CommaDelimited | Indented | LeadingWhitespace | TrailingWhitespace | PreferNewLine, - ObjectLiteralExpressionPropertiesForES5AndLater = ObjectLiteralExpressionProperties | AllowTrailingComma, - CallExpressionArguments = Parentheses | CommaDelimited | Indented | Fragment, - NewExpressionArguments = Parentheses | CommaDelimited | Indented | Optional | Fragment, - TemplateExpressionTemplateSpans = Fragment, - BlockStatements = CurlyBrackets | Indented | Whitespace | Scoped | PreferNewLine, - VariableDeclarations = CommaDelimited | Indented, - HeritageClauses = Indented | LeadingWhitespace | Fragment, - ClassMembers = CurlyBrackets | Indented | Whitespace | Scoped | PreferNewLine, - EnumMembers = CurlyBrackets | CommaDelimited | AllowTrailingComma | Indented | Scoped | Whitespace | PreferNewLine, - ModuleBlockStatements = CurlyBrackets | Indented | Whitespace | Scoped | PreferNewLine | LexicalEnvironment, - CaseBlockClauses = CurlyBrackets | Indented | Whitespace | Scoped | PreferNewLine, - ImportOrExportSpecifiers = CurlyBrackets | CommaDelimited | AllowTrailingComma | Indented | Whitespace, - CaseOrDefaultClauseStatements = Indented | Whitespace | PreferNewLine, - JsxElementChildren = PreferNewLine, - JsxAttributes = Fragment, - HeritageClauseTypes = CommaDelimited | Indented, - - FunctionBodyStatements = BlockStatements | LexicalEnvironment, - SourceFileStatements = PreferNewLine | LexicalEnvironment, - - MustEmitPrologueDirectivesFirst = PrintEmitHelpers | PrintExportStar + PreferNewLine = 1 << 9, // Prefer adding a LineTerminator between synthesized nodes. + PrintEmitHelpers = 1 << 10, // Emit any emit helpers along with the list. + PrintExportStar = 1 << 11, // Emit the __export helper for "export *". + LexicalEnvironment = 1 << 12, // Marks a lexical environment. } } \ No newline at end of file diff --git a/src/compiler/transform.ts b/src/compiler/transform.ts index 0e2f37d61f4..2c0791a5f93 100644 --- a/src/compiler/transform.ts +++ b/src/compiler/transform.ts @@ -63,78 +63,82 @@ namespace ts { return chainTransformationPhases(phases); } - export function transformFilesIfNeeded(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain): TransformationResult { - let compilerOptions = host.getCompilerOptions(); - if (compilerOptions.experimentalTransforms) { - return transformFiles(resolver, host, sourceFiles, transformationChain); - } - - return { sourceFiles }; + interface LexicalEnvironment { + tempFlags: TempFlags; + hoistedVariableDeclarations: VariableDeclaration[]; + hoistedFunctionDeclarations: FunctionDeclaration[]; } - export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain): TransformationResult { - interface LexicalEnvironment { - tempFlags: TempFlags; - hoistedVariableDeclarations: VariableDeclaration[]; - hoistedFunctionDeclarations: FunctionDeclaration[]; - } + const enum VisitFlags { + StatementBranch = 1 << 1, + ConciseBody = 1 << 2, + LexicalEnvironment = 1 << 3, + LexicalEnvironmentStarted = 1 << 4, + LexicalEnvironmentEnded = 1 << 5, + } - const enum VisitFlags { - StatementBranch = 1 << 1, - ConciseBody = 1 << 2, - LexicalEnvironment = 1 << 3, - LexicalEnvironmentStarted = 1 << 4, - LexicalEnvironmentEnded = 1 << 5, - } - - let compilerOptions = host.getCompilerOptions(); - let languageVersion = compilerOptions.target || ScriptTarget.ES3; + export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain): SourceFile[] { + // This is used to aggregate transform flags across the children of a node, + // as there is no `reduce`-like function similar to forEachChild. let transformFlags: TransformFlags; - let generatedNameSet: Map; - let tempVariableNameSet: Map; + + // These variables keep track of generated identifiers. + let generatedNameSet: Map = {}; + let tempVariableNameSet: Map = {}; let nodeToGeneratedName: string[] = []; let nodeToGeneratedIdentifier: Identifier[] = []; - let lexicalEnvironmentStackSize: number; + + // The lexical environment stack is used to track the allocation of temporary variables + // and the hoisting of variable and function declarations within a scope. + let lexicalEnvironmentStackSize: number = 0; let lexicalEnvironmentStack: LexicalEnvironment[] = []; let tempFlags: TempFlags; let hoistedVariableDeclarations: VariableDeclaration[]; let hoistedFunctionDeclarations: FunctionDeclaration[]; - let currentSourceFile: SourceFile; - let nodeStack: NodeStack; + + // Visit flags are used to request and keep track of information related to + // the current visit operation. let currentVisitFlags: VisitFlags; let requestedVisitFlags: VisitFlags; + + // This is used during a call to visitNode/visitNodes to ensure any + // node written out during the transformation is valid. let nodeTest: (node: Node) => boolean; + + // These variables are used by visitNode/visitNodes to keep track of + // differences between the source and output trees without introducing + // new function closures on each call. let writeOffset: number; let originalNodes: Node[]; let updatedNode: Node; let updatedNodes: Node[]; - let helpersEmitted: NodeCheckFlags; + + // Substitutions are used by Transformation Phases to perform additional + // transformations during final emit without further descent into the tree. + let bindingIdentifierSubstitution: (node: Identifier) => Identifier; let expressionSubstitution: (node: Expression) => Expression; + + // These are flags used during various transformation phases to inform + // later transformation phases about additional information from a transformation. let generatedNodeFlags: GeneratedNodeFlags[] = []; + + let nodeStack: NodeStack = createNodeStack(); + let currentSourceFile: SourceFile; let transformer: Transformer = { getEmitResolver: () => resolver, - getCompilerOptions: () => compilerOptions, - createParentNavigator: () => nodeStack.createParentNavigator(), - getRootNode: () => currentSourceFile, - getParentNode: () => nodeStack.getParent(), - getCurrentNode: () => nodeStack.getNode(), - tryPushNode: node => nodeStack.tryPushNode(node), - pushNode: node => nodeStack.pushNode(node), - popNode: () => nodeStack.popNode(), - setNode: node => nodeStack.setNode(node), - findAncestorNode: (match: (node: Node) => boolean) => nodeStack.findAncestorNode(match), - getDeclarationName, - getClassMemberPrefix, - makeUniqueName, + getCompilerOptions: () => host.getCompilerOptions(), + getSourceFile: () => currentSourceFile, + isUniqueName, getGeneratedNameForNode, nodeHasGeneratedName, createUniqueIdentifier, createTempVariable, - declareLocal, hoistVariableDeclaration, hoistFunctionDeclaration, getGeneratedNodeFlags, setGeneratedNodeFlags, + getBindingIdentifierSubstitution, + setBindingIdentifierSubstitution, getExpressionSubstitution, setExpressionSubstitution, startLexicalEnvironment, @@ -152,26 +156,51 @@ namespace ts { visitModuleBody, visitFunctionBody, visitConciseBody, - accept(node: Node, visitor: (node: Node, write: (node: Node) => void) => void) { - let wasPushed = node && nodeStack.tryPushNode(node); - node = acceptTransformer(transformer, node, visitor); - if (wasPushed) { - nodeStack.popNode(); - } - return node; - } + accept, + + // from NodeStack + createParentNavigator: () => nodeStack.createParentNavigator(), + getParentNode: () => nodeStack.getParentNode(), + getCurrentNode: () => nodeStack.getCurrentNode(), + tryPushNode: node => nodeStack.tryPushNode(node), + pushNode: node => nodeStack.pushNode(node), + popNode: () => nodeStack.popNode(), + setNode: node => nodeStack.setNode(node), + findAncestorNode: (match: (node: Node) => boolean) => nodeStack.findAncestorNode(match), }; + // Build the transformation pipeline using the supplied transformer. let transformation = transformationChain(transformer); - return { - sourceFiles: map(sourceFiles, transformSourceFile), - substitutions: { - getGeneratedNodeFlags, - expressionSubstitution, - } - }; + // Transform each source file. + return map(sourceFiles, transformSourceFile); + /** + * Transforms a source file. + * @param sourceFile The source file to transform. + */ + function transformSourceFile(sourceFile: SourceFile) { + if (isDeclarationFile(sourceFile)) { + return sourceFile; + } + + currentSourceFile = sourceFile; + + let visited = transformation(sourceFile); + if (visited !== sourceFile) { + updateFrom(sourceFile, visited); + } + + Debug.assert(nodeStack.getStackSize() === 0, "Incorrect node stack size after transformation."); + Debug.assert(lexicalEnvironmentStackSize === 0, "Incorrect lexical environment stack size after transformation."); + + currentSourceFile = undefined; + return visited; + } + + /** + * Gets additional context about a generated node. + */ function getGeneratedNodeFlags(node: Node) { let lastNode: Node; while (node) { @@ -187,49 +216,46 @@ namespace ts { return undefined; } + /** + * Sets additional contxt about a generated node. + */ function setGeneratedNodeFlags(node: Node, flags: GeneratedNodeFlags) { generatedNodeFlags[getNodeId(node)] = flags; } - function transformSourceFile(sourceFile: SourceFile) { - if (isDeclarationFile(sourceFile)) { - return sourceFile; - } - - currentSourceFile = sourceFile; - generatedNameSet = {}; - tempVariableNameSet = {}; - lexicalEnvironmentStackSize = 0; - nodeStack = createNodeStack(); - helpersEmitted = undefined; - - let visited = transformation(sourceFile); - if (visited !== sourceFile) { - visited.identifiers = assign(assign(clone(sourceFile.identifiers), generatedNameSet), tempVariableNameSet); - updateFrom(sourceFile, visited); - } - - currentSourceFile = undefined; - generatedNameSet = undefined; - tempVariableNameSet = undefined; - lexicalEnvironmentStackSize = undefined; - nodeStack = undefined; - helpersEmitted = undefined; - - return visited; + /** + * Gets the current substitution for binding identifiers. + */ + function getBindingIdentifierSubstitution(): (node: Identifier) => Identifier { + return bindingIdentifierSubstitution; } + /** + * Sets the current substitution for binding identifiers. + */ + function setBindingIdentifierSubstitution(substitution: (node: Identifier) => Identifier): void { + bindingIdentifierSubstitution = substitution; + } + + /** + * Gets the current substitution for expressions. + */ function getExpressionSubstitution(): (node: Expression) => Expression { return expressionSubstitution; } - function setExpressionSubstitution(substitution: (node: Expression) => Expression) { + /** + * Sets the current substitution for expressions. + */ + function setExpressionSubstitution(substitution: (node: Expression) => Expression): void { expressionSubstitution = substitution; } - // Return the next available name in the pattern _a ... _z, _0, _1, ... - // TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. - // Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ function makeTempVariableName(flags: TempFlags): string { if (flags && !(tempFlags & flags)) { let name = flags === TempFlags._i ? "_i" : "_n"; @@ -253,10 +279,12 @@ namespace ts { } } - // Generate a name that is unique within the current file and doesn't conflict with any names - // in global scope. The name is formed by adding an '_n' suffix to the specified base name, - // where n is a positive integer. Note that names generated by makeTempVariableName and - // makeUniqueName are guaranteed to never conflict. + /** + * Generate a name that is unique within the current file and doesn't conflict with any names + * in global scope. The name is formed by adding an '_n' suffix to the specified base name, + * where n is a positive integer. Note that names generated by makeTempVariableName and + * makeUniqueName are guaranteed to never conflict. + */ function makeUniqueName(baseName: string): string { // Find the first unique 'name_n', where n is a positive number if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { @@ -272,22 +300,34 @@ namespace ts { } } + /** + * Gets the generated name for a node. + */ function getGeneratedNameForNode(node: Node) { let id = getNodeId(node); - return nodeToGeneratedIdentifier[id] || (nodeToGeneratedIdentifier[id] = createIdentifier(getGeneratedNameTextForNode(node, id))); + return nodeToGeneratedIdentifier[id] || (nodeToGeneratedIdentifier[id] = generateNameForNode(node)); } + /** + * Gets a value indicating whether a node has a generated name. + */ function nodeHasGeneratedName(node: Node) { let id = getNodeId(node); return nodeToGeneratedName[id] !== undefined; } + /** + * Tests whether the provided name is unique. + */ function isUniqueName(name: string): boolean { return !resolver.hasGlobalName(name) && !hasProperty(currentSourceFile.identifiers, name) && !hasProperty(generatedNameSet, name); } + /** + * Tests whether the provided name is unique within a container. + */ function isUniqueLocalName(name: string, container: Node): boolean { container = getOriginalNode(container); for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) { @@ -301,14 +341,13 @@ namespace ts { return true; } - function getGeneratedNameTextForNode(node: Node, id: number) { - return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node))); - } - - function generateNameForNode(node: Node) { + /** + * Generates a name for a node. + */ + function generateNameForNode(node: Node): Identifier { switch (node.kind) { case SyntaxKind.Identifier: - return makeUniqueName((node).text); + return createUniqueIdentifier((node).text); case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: return generateNameForModuleOrEnum(node); @@ -324,76 +363,29 @@ namespace ts { case SyntaxKind.ComputedPropertyName: case SyntaxKind.Parameter: case SyntaxKind.TaggedTemplateExpression: - return makeTempVariableName(TempFlags.Auto); + return createTempVariable(TempFlags.Auto); } } function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { - let name = node.name.text; + let name = node.name; // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, node) ? name : makeUniqueName(name); + return isUniqueLocalName(name.text, node) ? name : createUniqueIdentifier(name.text); } function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { let expr = getExternalModuleName(node); let baseName = expr.kind === SyntaxKind.StringLiteral ? escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; - return makeUniqueName(baseName); + return createUniqueIdentifier(baseName); } function generateNameForExportDefault() { - return makeUniqueName("default"); + return createUniqueIdentifier("default"); } function generateNameForClassExpression() { - return makeUniqueName("class"); - } - - function createParentNavigator(): ParentNavigator { - return nodeStack.createParentNavigator(); - } - - function getRootNode(): SourceFile { - return currentSourceFile; - } - - function getCurrentNode(): Node { - return nodeStack.getNode(); - } - - function getParentNode(): Node { - return nodeStack.getParent(); - } - - function findAncestorNode(match: (node: Node) => node is T): T; - function findAncestorNode(match: (node: Node) => boolean): Node; - function findAncestorNode(match: (node: Node) => boolean) { - return nodeStack.findAncestorNode(match); - } - - function getDeclarationName(node: DeclarationStatement): Identifier; - function getDeclarationName(node: ClassLikeDeclaration): Identifier; - function getDeclarationName(node: Declaration): DeclarationName; - function getDeclarationName(node: Declaration): T | Identifier { - let name = node.name; - if (name) { - return nodeIsSynthesized(name) ? name : cloneNode(name); - } - else { - return getGeneratedNameForNode(node); - } - } - - function getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement) { - let expression: LeftHandSideExpression = getDeclarationName(node); - if (!(member.flags & NodeFlags.Static)) { - expression = createPropertyAccessExpression2( - expression, - createIdentifier("prototype") - ); - } - - return expression; + return createUniqueIdentifier("class"); } function createUniqueIdentifier(baseName: string): Identifier { @@ -402,18 +394,17 @@ namespace ts { } function createTempVariable(flags?: TempFlags): Identifier { - let name = makeTempVariableName(flags); - return createIdentifier(name); - } - - function declareLocal(baseName?: string): Identifier { - let local = baseName - ? createUniqueIdentifier(baseName) - : createTempVariable(TempFlags.Auto); - hoistVariableDeclaration(local); - return local; + let name = createIdentifier(); + name.tempFlags = flags; + getNodeId(name); + return name; + // let name = makeTempVariableName(flags); + // return createIdentifier(name); } + /** + * Records a hoisted variable declaration within a lexical environment. + */ function hoistVariableDeclaration(name: Identifier): void { if (!hoistedVariableDeclarations) { hoistedVariableDeclarations = []; @@ -422,6 +413,9 @@ namespace ts { hoistedVariableDeclarations.push(createVariableDeclaration2(name)); } + /** + * Records a hoisted function declaration within a lexical environment. + */ function hoistFunctionDeclaration(func: FunctionDeclaration): void { if (!hoistedFunctionDeclarations) { hoistedFunctionDeclarations = []; @@ -468,65 +462,25 @@ namespace ts { transformFlags |= aggregateTransformFlagsForThisNodeAndSubtree(child); } - function nextNodeIsLexicalEnvironment() { - requestedVisitFlags |= VisitFlags.LexicalEnvironment; - } - - function nextNodeIsStatementBranch() { - requestedVisitFlags |= VisitFlags.StatementBranch; - } - - function nextNodeIsConciseBody() { - requestedVisitFlags |= VisitFlags.ConciseBody; - } - - function markLexicalEnvironmentStart() { - currentVisitFlags |= VisitFlags.LexicalEnvironmentStarted; - } - - function resetLexicalEnvironmentStart() { - currentVisitFlags &= ~VisitFlags.LexicalEnvironmentStarted; - } - - function markLexicalEnvironmentEnd() { - currentVisitFlags |= VisitFlags.LexicalEnvironmentEnded; - } - - function resetLexicalEnvironmentEnd() { - currentVisitFlags &= ~VisitFlags.LexicalEnvironmentEnded; - } - - function thisNodeIsLexicalEnvironment() { - return !!(currentVisitFlags & VisitFlags.LexicalEnvironment); - } - - function lexicalEnvironmentStartWasMarked() { - return !!(currentVisitFlags & VisitFlags.LexicalEnvironmentStarted); - } - - function lexicalEnvironmentEndWasMarked() { - return !!(currentVisitFlags & VisitFlags.LexicalEnvironmentEnded); - } - - function thisNodeIsStatementBranch() { - return !!(currentVisitFlags & VisitFlags.StatementBranch); - } - - function thisNodeIsConciseBody() { - return !!(currentVisitFlags & VisitFlags.ConciseBody); - } - + /** + * Callback used to write a one or more nodes to a single output node. + * If more than one node is written and the output points to a Statement property of a + * parent node, the result is lifted to a Block containing multiple statements. + * If more than one node is written and the output points to the body of an Arrow Function, + * the result is lifted to a Block consisting of a return statement. + * Otherwise, If more than one node is written it is an error. + */ function writeNode(node: Node) { if (!node) { return; } - Debug.assert(!nodeTest || nodeTest(node), "Wrong node type after visit."); + Debug.assert(!nodeTest || nodeTest(node), `Wrong node type after visit: ${formatSyntaxKind(node.kind)}`); aggregateTransformFlags(node); if (!updatedNode) { updatedNode = node; } - else if (thisNodeIsStatementBranch()) { + else if (currentVisitFlags & VisitFlags.StatementBranch) { if (!updatedNodes) { updatedNodes = []; writeStatementNode(updatedNode); @@ -534,25 +488,31 @@ namespace ts { } writeStatementNode(node); } - else if (thisNodeIsConciseBody()) { + else if (currentVisitFlags & VisitFlags.ConciseBody) { if (!updatedNodes) { updatedNodes = []; - writeFunctionBodyNode(updatedNode); + writeConciseBodyNode(updatedNode); updatedNode = createBlock(updatedNodes); } - writeFunctionBodyNode(node); + writeConciseBodyNode(node); } else { Debug.fail("Too many nodes written to output."); } } + /** + * Writes a node to a Statement property of a parent node. + */ function writeStatementNode(node: Node) { Debug.assert(isStatementNode(updatedNode), "Statement expected."); updatedNodes.push(node); } - function writeFunctionBodyNode(node: Node) { + /** + * Writes a node to a ConciseBody property of a parent ArrowFunction node. + */ + function writeConciseBodyNode(node: Node) { if (isExpressionNode(node)) { updatedNodes.push(createReturnStatement(node)); } @@ -562,6 +522,9 @@ namespace ts { } } + /** + * Writes one or more nodes to a NodeArray. + */ function writeNodeToNodeArray(node: Node) { if (!node) { return; @@ -581,10 +544,16 @@ namespace ts { } } + /** + * Reads a single Node. + */ function readNode(): Node { return updatedNode; } + /** + * Reads one or more Nodes as a NodeArray. + */ function readNodeArray(): NodeArray { if (updatedNodes) { return createNodeArray(updatedNodes, /*location*/ >originalNodes); @@ -597,6 +566,11 @@ namespace ts { } } + /** + * Executes a callback function to emit new nodes to an output array or write callback. + * @param callback The callback to execute. + * @param out Either an array to which to write the results, or a callback used to write the results. + */ function createNodes(callback: (write: (node: TOut) => void) => void, out?: ((node: TOut) => void) | TOut[]): NodeArray { let write: (node: Node) => void; let readNodes: () => NodeArray; @@ -644,8 +618,34 @@ namespace ts { return resultNodes as NodeArray; } - function visitNodeOrNodes(node: Node, nodes: Node[], start: number, count: number, visitor: (node: Node, write: (node: Node) => void) => void, - write: (node: Node) => void, readNode?: () => Node, readNodes?: () => NodeArray, out?: Node[], test?: (node: Node) => boolean): Node | NodeArray { + /** + * Visits either a single node or an array of nodes using a general-purpose visitor callback. + * + * When visiting an array of nodes, it is acceptable to write more or less nodes to the output. + * + * If the same values are written in the same order as the original node array, the original + * node array is returned. If more or fewer values are written, or if any value differs from the source in order or reference + * equality, a new node array will be returned. This is to provide reference equality for the various update functions + * used by the accept function below. + * + * This function also ensures that each node is pushed onto the node stack before calling the + * visitor, and popped off of the node stack once the visitor has returned. + * + * The cardinality of this function is expected to be *:* (many-to-many). + * + * The node test is used to enforce that each output node matches the expected kind of the + * result. + * + * @param nodes The array of Nodes to visit. + * @param visitor A callback executed to write the results of visiting each node or its children. + * @param test A node test used to validate the result of visiting each node. + * @param start An offset into nodes at which to start visiting. + * @param count A the number of nodes to visit. + */ + function visitNodeOrNodes(node: Node, nodes: Node[], start: number, count: number, + visitor: (node: Node, write: (node: Node) => void) => void, write: (node: Node) => void, + readNode?: () => Node, readNodes?: () => NodeArray, out?: Node[], + test?: (node: Node) => boolean): Node | NodeArray { let resultNode: Node; let resultNodes: NodeArray; let savedOriginalNodes: typeof originalNodes; @@ -655,6 +655,8 @@ namespace ts { let savedNodeTest: typeof nodeTest; let savedCurrentVisitFlags: typeof currentVisitFlags; + Debug.assert(!(node && nodes), "`node` and `nodes` may not both be specified."); + // If we have no work to do, clear the requested visit flags and exit if (!node && !nodes) { // If we don't have a `read` argument, then we should not affect @@ -690,7 +692,7 @@ namespace ts { requestedVisitFlags = undefined; // These flags indicate a new lexical environment should be introduced when/if we visit the children of this node. - if (thisNodeIsLexicalEnvironment()) { + if (currentVisitFlags & VisitFlags.LexicalEnvironment) { pushLexicalEnvironment(); } } @@ -710,7 +712,7 @@ namespace ts { // Fix start and count let len = nodes.length; start = start < 0 ? 0 : start || 0; - count = count > len - start ? len - start : count || len - start; + count = count > len - start ? len - start : count === undefined ? len - start : count; // Visit each input node for (let i = 0; i < count; ++i) { @@ -737,7 +739,7 @@ namespace ts { } // If a new lexical environment had been requested, we need to include it here - if (thisNodeIsLexicalEnvironment()) { + if (currentVisitFlags & VisitFlags.LexicalEnvironment) { if (hoistedVariableDeclarations || hoistedFunctionDeclarations) { let statements: Statement[]; if (isSourceFile(resultNode) || isModuleBody(resultNode) || isFunctionBody(resultNode)) { @@ -828,6 +830,13 @@ namespace ts { tempFlags = savedLexicalEnvironment.tempFlags; hoistedVariableDeclarations = savedLexicalEnvironment.hoistedVariableDeclarations; hoistedFunctionDeclarations = savedLexicalEnvironment.hoistedFunctionDeclarations; + + // Whenenver we empty the lexical environment stack, we need to save all temporary + // variable names generated in the source file to prevent reuse in other steps or phases. + if (lexicalEnvironmentStackSize === 0 && !isEmpty(tempVariableNameSet)) { + generatedNameSet = extend(generatedNameSet, tempVariableNameSet); + tempVariableNameSet = { }; + } } function writeLexicalEnvironment(write: (node: Statement) => void): void { @@ -916,6 +925,20 @@ namespace ts { requestedVisitFlags |= VisitFlags.StatementBranch; return visitNode(node, visitor, isStatementNode); } + + function accept(node: Node, visitor: (node: Node, write: (node: Node) => void) => void) { + if (!node) { + return undefined; + } + + let wasPushed = nodeStack.tryPushNode(node); + node = acceptTransformer(transformer, node, visitor); + if (wasPushed) { + nodeStack.popNode(); + } + + return node; + } } export function chainTransformationPhases(phases: TransformationPhase[]): TransformationChain { @@ -988,4 +1011,29 @@ namespace ts { function buildNaryTransformation(steps: Transformation[]): Transformation { return node => steps.reduce(runStep, node); } + + function formatSyntaxKind(kind: SyntaxKind) { + let text = String(kind); + if ((ts).SyntaxKind) { + text += " (" + (ts).SyntaxKind[kind] + ")"; + } + + return text; + } + + /** + * Emits file prologue directives prior to a module body. + */ + export function writePrologueDirectives(statements: NodeArray, write: (node: Statement) => void): number { + for (let i = 0; i < statements.length; ++i) { + if (isPrologueDirective(statements[i])) { + write(statements[i]); + } + else { + return i; + } + } + + return statements.length; + } } \ No newline at end of file diff --git a/src/compiler/transforms/destructuring.ts b/src/compiler/transforms/destructuring.ts index fde6a0fb854..ca268c8eec8 100644 --- a/src/compiler/transforms/destructuring.ts +++ b/src/compiler/transforms/destructuring.ts @@ -9,7 +9,7 @@ namespace ts { * @param visitor An optional visitor used to visit the initializers of a binding pattern. */ export function flattenVariableDestructuring(transformer: Transformer, node: VariableDeclaration, write: (node: VariableDeclaration) => void, visitor?: (node: Node, write: (node: Node) => void) => void): void { - transformDestructuring(transformer, node, /*writeExpression*/ undefined, write, visitor, node.initializer); + transformDestructuring(transformer, node, /*writeExpression*/ undefined, write, visitor); } /** @@ -126,7 +126,7 @@ namespace ts { } } else { - emitAssignment(name, value, /*isTempVariable*/ false, write); + emitAssignment(name, value, /*isTempVariable*/ false, /*originalNode*/ target, write); } } @@ -156,7 +156,7 @@ namespace ts { emitArrayLiteralAssignment(target, value, write); } else if (isIdentifier(target)) { - emitAssignment(target, value, /*isTempVariable*/ false, write); + emitAssignment(target, value, /*isTempVariable*/ false, /*originalNode*/ undefined, write); } else { Debug.fail(); @@ -201,13 +201,20 @@ namespace ts { } } - function emitAssignment(left: Identifier, right: Expression, isTempVariable: boolean, write: (node: Expression | VariableDeclaration) => void): void { + function emitAssignment(left: Identifier, right: Expression, isTempVariable: boolean, originalNode: Node, write: (node: Expression | VariableDeclaration) => void): void { + let node: VariableDeclaration | Expression; if (isVariableDeclarationList) { - write(createVariableDeclaration2(left, right)); + node = createVariableDeclaration2(left, right); } else { - write(createAssignmentExpression(left, right)); + node = createAssignmentExpression(left, right); } + + if (originalNode) { + node.original = originalNode; + } + + write(node); } function ensureIdentifier(value: Expression, reuseIdentifierExpressions: boolean, write: (node: Expression | VariableDeclaration) => void) { @@ -220,7 +227,7 @@ namespace ts { hoistVariableDeclaration(temp); } - emitAssignment(temp, value, /*isTempVariable*/ true, write); + emitAssignment(temp, value, /*isTempVariable*/ true, /*originalNode*/ undefined, write); return temp; } } diff --git a/src/compiler/transforms/es6.ts b/src/compiler/transforms/es6.ts index 5989e49ce6e..a364706e6f2 100644 --- a/src/compiler/transforms/es6.ts +++ b/src/compiler/transforms/es6.ts @@ -9,12 +9,9 @@ namespace ts { endLexicalEnvironment, getParentNode, findAncestorNode, - declareLocal, getGeneratedNameForNode, createTempVariable, hoistVariableDeclaration, - getDeclarationName, - getClassMemberPrefix, pushNode, popNode, pipeNode, @@ -36,6 +33,11 @@ namespace ts { let languageVersion = compilerOptions.target || ScriptTarget.ES3; let resolver = transformer.getEmitResolver(); let currentSourceFile: SourceFile; + let noSubstitution: boolean[] = []; + let savedBindingIdentifierSubstitution = transformer.getBindingIdentifierSubstitution(); + transformer.setBindingIdentifierSubstitution(substituteBindingIdentifierWithFallback); + let savedExpressionSubstitution = transformer.getExpressionSubstitution(); + transformer.setExpressionSubstitution(substituteExpressionWithFallback); return transformES6; @@ -76,7 +78,7 @@ namespace ts { return; } - if (node.transformFlags & TransformFlags.ThisNodeIsES6) { + if (node.transformFlags & TransformFlags.ES6) { visitorWorker(node, write); } else if (node.transformFlags & TransformFlags.ContainsES6) { @@ -119,6 +121,10 @@ namespace ts { visitVariableStatement(node, write); break; + case SyntaxKind.VariableDeclaration: + visitVariableDeclaration(node, write); + break; + case SyntaxKind.VariableDeclarationList: visitVariableDeclarationList(node, write); break; @@ -174,17 +180,36 @@ namespace ts { visitSuperKeyword(node, write); break; - case SyntaxKind.ThisKeyword: - visitThisKeyword(node, write); + case SyntaxKind.MethodDeclaration: + visitMethodDeclaration(node, write); + break; + + case SyntaxKind.SourceFile: + visitSourceFileNode(node, write); break; default: - Debug.fail("Encountered unhandled node kind when transforming ES6 syntax."); + let original = getOriginalNode(node); + let location = ""; + if (!nodeIsSynthesized(original)) { + let lineCol = getLineAndCharacterOfPosition(currentSourceFile, node.pos); + location = currentSourceFile.fileName + "(" + (lineCol.line + 1) + "," + lineCol.character + "): "; + } + Debug.fail(`${location}Encountered unhandled node kind ${formatSyntaxKind(node.kind)} when transforming ES6 syntax.`); write(accept(node, visitor)); break; } } + function formatSyntaxKind(kind: SyntaxKind) { + let text = String(kind); + if ((ts).SyntaxKind) { + text += " (" + (ts).SyntaxKind[kind] + ")"; + } + + return text; + } + function visitClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void): void { visitClassLikeDeclaration(node, write); } @@ -193,7 +218,7 @@ namespace ts { visitClassLikeDeclaration(node, write); } - function visitClassLikeDeclaration(node: ClassLikeDeclaration, write: (node: Expression | Statement) => void): void { + function visitClassLikeDeclaration(node: ClassExpression | ClassDeclaration, write: (node: Expression | Statement) => void): void { let name = getDeclarationName(node); let statements = flattenNode(node, emitClassBody); let baseTypeNode = getClassExtendsHeritageClauseElement(node); @@ -217,16 +242,16 @@ namespace ts { } } - function emitClassBody(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + function emitClassBody(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void): void { startLexicalEnvironment(); emitExtendsHelperIfNeeded(node, write); emitConstructor(node, write); emitMemberFunctions(node, write); - write(createReturnStatement(getDeclarationName(node))); + write(createReturnStatement(node.name ? makeSynthesized(node.name) : getGeneratedNameForNode(node))); endLexicalEnvironment(write); } - function emitExtendsHelperIfNeeded(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + function emitExtendsHelperIfNeeded(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void): void { if (getClassExtendsHeritageClauseElement(node)) { let extendsExpr = createExtendsHelperCall(getDeclarationName(node)); let extendsStmt = createExpressionStatement(extendsExpr); @@ -235,7 +260,7 @@ namespace ts { } } - function emitConstructor(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + function emitConstructor(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void): void { let ctor = getFirstConstructorWithBody(node); let parameters: ParameterDeclaration[]; let statements: Statement[]; @@ -252,7 +277,7 @@ namespace ts { } let name = getDeclarationName(node); - let constructorFunction = createFunctionDeclaration2(name, parameters, createBlock(statements)); + let constructorFunction = createFunctionDeclaration2(name, parameters, createBlock(statements, /*location*/ undefined, NodeFlags.MultiLine)); startOnNewLine(constructorFunction); write(constructorFunction); } @@ -339,24 +364,27 @@ namespace ts { let initExpr = visitNode(initializer, visitor, isExpressionNode); let assignExpr = createAssignmentExpression(name, initExpr); let assignStmt = createExpressionStatement(assignExpr); - let trueStmt = createBlock([assignStmt]); + let trueStmt = createBlock([assignStmt], /*location*/ undefined, NodeFlags.SingleLine); let ifStmt = createIfStatement(equalityExpr, trueStmt); startOnNewLine(ifStmt); write(ifStmt); } function shouldEmitRestParameter(node: ParameterDeclaration) { - return node.dotDotDotToken && !(node.flags & NodeFlags.Generated); + return node && node.dotDotDotToken && !(node.flags & NodeFlags.Generated); } function emitRestParameter(node: FunctionLikeDeclaration, write: (node: Statement) => void): void { let lastParam = lastOrUndefined(node.parameters); if (!shouldEmitRestParameter(lastParam)) { + if (node && node.name && (node.name).text === "append") { + console.log("no rest in append"); + } return; } // var param = []; - let name = getDeclarationName(lastParam); + let name = makeSynthesized(lastParam.name); let restIndex = node.parameters.length - 1; let paramVarStmt = createVariableStatement3(name, createArrayLiteralExpression([])); startOnNewLine(paramVarStmt); @@ -392,13 +420,13 @@ namespace ts { } } - function emitMemberFunctions(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + function emitMemberFunctions(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void): void { for (let member of node.members) { if (isSemicolonClassElement(member)) { visitSemicolonClassElement(member, write); } else if (isMethodDeclaration(member)) { - visitMethodDeclaration(node, member, write); + visitClassMethodDeclaration(node, member, write); } else if (isGetAccessor(member) || isSetAccessor(member)) { let accessors = getAllAccessorDeclarations(node.members, member); @@ -416,7 +444,7 @@ namespace ts { write(stmt); } - function visitMethodDeclaration(node: ClassLikeDeclaration, member: MethodDeclaration, write: (node: Statement) => void): void { + function visitClassMethodDeclaration(node: ClassExpression | ClassDeclaration, member: MethodDeclaration, write: (node: Statement) => void): void { let prefix = getClassMemberPrefix(node, member); let propExpr = createMemberAccessForPropertyName(prefix, visitNode(member.name, visitor, isPropertyName)); let funcExpr = transformFunctionLikeToExpression(member); @@ -450,13 +478,17 @@ namespace ts { function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location?: TextRange, name?: Identifier): FunctionExpression { let parameters = visitNodes(node.parameters, visitor, isParameter); let statements = flattenNode(node, emitFunctionBody); - return createFunctionExpression2(name, parameters, createBlock(statements), location); + let expression = createFunctionExpression2(name, parameters, createBlock(statements), location); + expression.original = node; + return expression; } function visitFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void): void { let parameters = visitNodes(node.parameters, visitor, isParameter); let statements = flattenNode(node, emitFunctionBody); - write(createFunctionDeclaration2(node.name, parameters, createBlock(statements), /*location*/ node)); + let declaration = createFunctionDeclaration2(node.name, parameters, createBlock(statements), /*location*/ node); + declaration.original = node; + write(declaration); } function emitFunctionBody(node: FunctionLikeDeclaration, write: (node: Statement) => void): void { @@ -472,12 +504,7 @@ namespace ts { else { let expr = visitNode(body, visitor, isExpressionNode); if (expr) { - let returnStmt = createReturnStatement(expr); - if (!childNodeStartPositionIsOnSameLine(currentSourceFile, node, body)) { - startOnNewLine(returnStmt); - } - - write(returnStmt); + write(createReturnStatement(expr)); } } endLexicalEnvironment(write); @@ -496,19 +523,55 @@ namespace ts { function visitVariableDeclarationList(node: VariableDeclarationList, write: (node: VariableDeclarationList) => void): void { // TODO(rbuckton): let/const let declarations = visitNodes(node.declarations, visitVariableDeclaration, isVariableDeclaration); - write(updateVariableDeclarationList(node, declarations)); + write(createVariableDeclarationList(declarations, node)); } function visitVariableDeclaration(node: VariableDeclaration, write: (node: VariableDeclaration) => void): void { - if (isBindingPattern(node.name)) { + let name = node.name; + if (isBindingPattern(name)) { flattenVariableDestructuring(transformer, node, write, visitor); } else { - // TODO(rbuckton): Is there any reason we should hit this branch? - write(accept(node, visitor)); + let initializer = node.initializer; + if (!initializer) { + // downlevel emit for non-initialized let bindings defined in loops + // for (...) { let x; } + // should be + // for (...) { var = void 0; } + // this is necessary to preserve ES6 semantic in scenarios like + // for (...) { let x; console.log(x); x = 1 } // assignment on one iteration should not affect other iterations + let isUninitializedLet = + (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) && + (getCombinedNodeFlags(transformer) & NodeFlags.Let); + + // NOTE: default initialization should not be added to let bindings in for-in\for-of statements + if (isUninitializedLet && + !isForBinding(findAncestorNode(isIterationStatement), node)) { + initializer = createVoidZeroExpression(); + } + } + else { + initializer = visitNode(initializer, visitor, isExpressionNode); + } + + write(updateVariableDeclaration(node, name, /*type*/ undefined, initializer)); } } + function isForBinding(container: IterationStatement, node: VariableDeclaration) { + if (isForInStatement(container) || isForOfStatement(container)) { + let initializer = container.initializer; + if (isVariableDeclarationList(initializer)) { + return node === initializer.declarations[0]; + } + } + return false; + } + + function isIterationStatement(node: Node): node is IterationStatement { + return isForInStatement(node) || isForOfStatement(node) || isForStatement(node) || isDoStatement(node) || isWhileStatement(node); + } + function visitForOfStatement(node: ForOfStatement, write: (node: Statement) => void): void { // The following ES6 code: // @@ -578,7 +641,7 @@ namespace ts { else { // The following call does not include the initializer, so we have // to emit it separately. - declarations.push(createVariableDeclaration2(declaration.name, rhsIterationValue)); + declarations.push(updateVariableDeclaration(declaration, declaration.name, /*type*/ undefined, rhsIterationValue)); } } else { @@ -632,7 +695,8 @@ namespace ts { // For computed properties, we need to create a unique handle to the object // literal so we can modify it without risking internal assignments tainting the object. - let temp = declareLocal(); + let temp = createTempVariable(); + hoistVariableDeclaration(temp); // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. let initialProperties = visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties); @@ -640,11 +704,27 @@ namespace ts { let expressions: Expression[] = []; expressions.push(createAssignmentExpression(temp, createObjectLiteralExpression(initialProperties))) pipeNodes(properties, (property, write) => emitObjectLiteralElementAsExpression(property, write, node, temp), expressions, numInitialNonComputedProperties); - expressions.push(temp); + + // We need to clone the temporary identifier so that we can write it on a + // new line + let clone = cloneNode(temp); + if (node.flags & NodeFlags.MultiLine) { + startOnNewLine(clone); + } + + expressions.push(clone); write(createParenthesizedExpression(inlineExpressions(expressions))); } + function visitMethodDeclaration(node: MethodDeclaration, write: (node: ObjectLiteralElement) => void): void { + let name = node.name; + if (isIdentifier(name)) { + let funcExpr = transformFunctionLikeToExpression(node, node); + write(createPropertyAssignment(node.name, funcExpr, node)); + } + } + function emitObjectLiteralElementAsExpression(property: ObjectLiteralElement, write: (node: Expression) => void, node: ObjectLiteralExpression, receiver: Identifier): void { if (isGetAccessor(property) || isSetAccessor(property)) { let accessors = getAllAccessorDeclarations(node.properties, property); @@ -672,7 +752,11 @@ namespace ts { Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind); } - write(createAssignmentExpression(qualifiedName, initializer)); + let assignment = createAssignmentExpression(qualifiedName, initializer); + if (node.flags & NodeFlags.MultiLine) { + startOnNewLine(assignment); + } + write(assignment); } } @@ -696,12 +780,18 @@ namespace ts { function visitCallExpression(node: CallExpression, write: (node: LeftHandSideExpression) => void): void { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. - if (forEach(node.arguments, isSpreadElementExpression)) { + if (node.transformFlags & TransformFlags.ContainsSpreadElementExpression) { emitCallWithSpread(node, write); } else { + Debug.assert( + node.expression.kind === SyntaxKind.SuperKeyword || + node.expression.kind === SyntaxKind.PropertyAccessExpression && + (node.expression).expression.kind === SyntaxKind.SuperKeyword); + let expression = visitNode(node.expression, visitor, isExpressionNode); - let thisArg = mapNode(createThisKeyword(), visitThisKeyword); + let container = getThisContainer(transformer, /*includeArrowFunctions*/ true); + let thisArg = isArrowFunction(container) ? createIdentifier("_this") : createThisKeyword(); let args = visitNodes(node.arguments, visitor, isExpressionNode); let callCall = createCallCall(expression, thisArg, args, /*location*/ node); write(callCall); @@ -714,16 +804,16 @@ namespace ts { let target: Expression; if (isPropertyAccessExpression(callee)) { // Target will be emitted as "this" argument. - ({ target, expression } = getCallTarget(visitNode(callee.expression, visitor, isLeftHandSideExpression))); + ({ target, expression } = visitCallTarget(callee.expression)); expression = createPropertyAccessExpression2(expression, callee.name); } else if (isElementAccessExpression(callee)) { // target will be emitted as "this" argument. - ({ target, expression } = getCallTarget(visitNode(callee.expression, visitor, isLeftHandSideExpression))); + ({ target, expression } = visitCallTarget(callee.expression)); expression = createElementAccessExpression2(expression, visitNode(callee.argumentExpression, visitor, isExpressionNode)); } else if (isSuperKeyword(callee)) { - target = mapNode(createThisKeyword(/*location*/ callee), visitThisKeyword); + target = createThisKeyword(/*location*/ callee); expression = createIdentifier("_super"); } else { @@ -740,7 +830,7 @@ namespace ts { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. if (forEach(node.arguments, isSpreadElementExpression)) { - let { target, expression } = getCallTarget(visitNode(node.expression, visitor, isExpressionNode)); + let { target, expression } = visitCallTarget(node.expression); let argumentsArray = spreadElements(node.arguments, /*needsUniqueCopy*/ false, createVoidZeroExpression()); let bindApply = createApplyCall(createPropertyAccessExpression3(expression, "bind"), target, argumentsArray); write(createNewExpression(createParenthesizedExpression(bindApply), /*typeArguments*/ undefined, [])); @@ -759,17 +849,24 @@ namespace ts { return node; } - function getCallTarget(expression: Expression) { + function visitCallTarget(node: LeftHandSideExpression) { + let expression = visitNode(node, visitor, isLeftHandSideExpression); let target: PrimaryExpression; - if (isIdentifier(expression) || isThisKeyword(expression) || isSuperKeyword(expression)) { - target = cloneNode(expression); + if (isIdentifier(expression)) { + target = makeSynthesized(expression); + } + else if (isThisKeyword(node) || isSuperKeyword(node)) { + target = createThisKeyword(); + target.original = node; } else { - target = declareLocal(); + let temp = createTempVariable(); + hoistVariableDeclaration(temp); + target = temp; expression = createParenthesizedExpression(createAssignmentExpression(target, expression)); } - return { target, expression }; + return { expression, target }; } function spreadElements(elements: Expression[], needsUniqueCopy: boolean, leadingExpression?: Expression) { @@ -787,7 +884,8 @@ namespace ts { segments.push(createArrayLiteralExpression(visitNodes(elements.slice(start, i), visitor, isExpressionNode))); } - segments.push(needsUniqueCopy ? createSliceCall(element.expression) : element.expression); + let expression = visitNode(element.expression, visitor, isExpressionNode); + segments.push(expression); start = i + 1; } } @@ -797,6 +895,10 @@ namespace ts { } if (segments.length === 1) { + if (!leadingExpression && needsUniqueCopy && isSpreadElementExpression(elements[0])) { + return createSliceCall(segments[0]); + } + return parenthesizeForAccess(segments[0]); } @@ -813,7 +915,9 @@ namespace ts { let tag = visitNode(node.tag, visitor, isExpressionNode); // Allocate storage for the template site object - let templateObj = declareLocal(); + let templateObj = createTempVariable(); + hoistVariableDeclaration(templateObj); + let rawObj = createPropertyAccessExpression3(templateObj, "raw"); // Build up the template arguments and the raw and cooked strings for the template. @@ -969,17 +1073,6 @@ namespace ts { write(_super); } - function visitThisKeyword(node: PrimaryExpression, write: (node: LeftHandSideExpression) => void): void { - let container = getThisContainer(transformer, /*includeArrowFunctions*/ true); - if (isArrowFunction(container)) { - let thisName = createIdentifier("_this"); - write(thisName); - } - else { - write(node); - } - } - function visitExpressionStatement(node: ExpressionStatement, write: (node: Statement) => void): void { if (node.flags & NodeFlags.Generated) { write(createDefaultSuperCall()); @@ -990,6 +1083,80 @@ namespace ts { } } + function visitSourceFileNode(node: SourceFile, write: (node: SourceFile) => void): void { + let statements = flattenNode(node, emitSourceFileBody); + write(updateSourceFileNode(node, statements, node.endOfFileToken)); + } + + function emitSourceFileBody(node: SourceFile, write: (node: Statement) => void): void { + let statementOffset = writePrologueDirectives(node.statements, write); + emitCaptureThisForNodeIfNeeded(node, write); + pipeNodes(node.statements, visitSourceElement, write, statementOffset); + } + + function visitSourceElement(node: Statement, write: (node: Statement) => void): void { + write(visitNode(node, visitor, isStatementNode)); + } + + function substituteBindingIdentifierWithFallback(node: Identifier): Identifier { + let substitute = noSubstitution[getNodeId(node)] ? node : substituteBindingIdentifier(node); + return savedBindingIdentifierSubstitution ? savedBindingIdentifierSubstitution(substitute) : substitute; + } + + function substituteBindingIdentifier(node: Identifier): Identifier { + if (isNameOfNestedRedeclaration(node)) { + let name = getGeneratedNameForNode(node); + noSubstitution[getNodeId(name)] = true; + return name; + } + return node; + } + + function substituteExpressionWithFallback(node: Expression): Expression { + let substitute = noSubstitution[getNodeId(node)] ? node : substituteExpression(node); + return savedExpressionSubstitution ? savedExpressionSubstitution(substitute) : substitute; + } + + function substituteExpression(node: Expression): Expression { + if (isIdentifier(node)) { + return substituteExpressionIdentifier(node); + } + else if (isThisKeyword(node)) { + return substituteThisKeyword(node); + } + return node; + } + + function substituteExpressionIdentifier(node: Identifier): Identifier { + let declaration = resolver.getReferencedNestedRedeclaration(node); + if (declaration) { + return getGeneratedNameForNode(declaration.name); + } + return node; + } + + function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression { + let originalNode = getOriginalNode(node); + let container = getThisContainer(originalNode, /*includeArrowFunctions*/ true); + if (isArrowFunction(container)) { + return createIdentifier("_this"); + } + return node; + } + + function isNameOfNestedRedeclaration(node: Identifier) { + let parent = transformer.getParentNode(); + switch (parent.kind) { + case SyntaxKind.BindingElement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.VariableDeclaration: + return (parent).name === node + && resolver.isNestedRedeclaration(parent); + } + return false; + } + function createDefaultSuperCall() { let superName = createIdentifier("_super"); let thisExpr = createThisKeyword(); @@ -999,5 +1166,14 @@ namespace ts { startOnNewLine(statement); return statement; } + + function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) { + return node.name ? makeSynthesized(node.name) : getGeneratedNameForNode(node); + } + + function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) { + let expression = getDeclarationName(node); + return member.flags & NodeFlags.Static ? expression : createPropertyAccessExpression3(expression, "prototype"); + } } } \ No newline at end of file diff --git a/src/compiler/transforms/module/module.ts b/src/compiler/transforms/module/module.ts index d9e9b502c02..d30c378e419 100644 --- a/src/compiler/transforms/module/module.ts +++ b/src/compiler/transforms/module/module.ts @@ -10,7 +10,6 @@ namespace ts { }; let { - makeUniqueName, getGeneratedNameForNode, hoistVariableDeclaration, hoistFunctionDeclaration, diff --git a/src/compiler/transforms/module/system.ts b/src/compiler/transforms/module/system.ts index 4c902ecfdef..37d7613c4f2 100644 --- a/src/compiler/transforms/module/system.ts +++ b/src/compiler/transforms/module/system.ts @@ -9,7 +9,6 @@ namespace ts { } let { - makeUniqueName, createUniqueIdentifier, getGeneratedNameForNode, hoistVariableDeclaration, @@ -961,10 +960,16 @@ namespace ts { } function createModuleDefinitionObject(setters: Expression[], statements: Statement[]) { - return createObjectLiteralExpression2({ - "setters": createArrayLiteralExpression(setters), - "execute": createFunctionExpression3([], createBlock(statements)) - }); + let properties: ObjectLiteralElement[] = []; + let settersProp = createPropertyAssignment2("setters", createArrayLiteralExpression(setters)); + startOnNewLine(settersProp); + properties.push(settersProp); + + let executeProp = createPropertyAssignment2("execute", createFunctionExpression3([], createBlock(statements))); + startOnNewLine(executeProp); + properties.push(executeProp); + + return createObjectLiteralExpression(properties); } function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) { diff --git a/src/compiler/transforms/ts.ts b/src/compiler/transforms/ts.ts index 5bff2514047..c9ee4073c8d 100644 --- a/src/compiler/transforms/ts.ts +++ b/src/compiler/transforms/ts.ts @@ -11,11 +11,9 @@ namespace ts { pushNode, popNode, findAncestorNode, - declareLocal, getGeneratedNameForNode, + createTempVariable, hoistVariableDeclaration, - getDeclarationName, - getClassMemberPrefix, pipeNode, pipeNodes, mapNode, @@ -248,14 +246,20 @@ namespace ts { visitParameter(node, write); break; + case SyntaxKind.ParenthesizedExpression: + // ParenthesizedExpressions are TypeScript if their expression is a + // TypeAssertion or AsExpression + visitParenthesizedExpression(node, write); + break; + case SyntaxKind.TypeAssertionExpression: // TypeScript type assertions are removed, but their subtrees are preserved. - write((node).expression); + write(visitNode((node).expression, visitor, isExpressionNode)); break; case SyntaxKind.AsExpression: // TypeScript `as` expressions are removed, but their subtrees are preserved. - write((node).expression); + write(visitNode((node).expression, visitor, isExpressionNode)); break; case SyntaxKind.EnumDeclaration: @@ -283,6 +287,11 @@ namespace ts { visitImportEqualsDeclaration(node, write); break; + case SyntaxKind.BinaryExpression: + // Exponentiation operator + visitBinaryExpression(node, write); + break; + default: Debug.fail("Encountered unhandled node kind when transforming TypeScript syntax."); write(accept(node, visitor)); @@ -303,7 +312,7 @@ namespace ts { */ function visitClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void): void { // Get the name of the class - let name = getDeclarationName(node); + let name = node.name || getGeneratedNameForNode(node); // Visit the base type node for the class. let baseTypeNode = mapNode(getClassExtendsHeritageClauseElement(node), visitExpressionWithTypeArguments); @@ -311,7 +320,7 @@ namespace ts { // Create a synthetic constructor for the class (if necessary), and visit the members of the class. let classMembers: ClassElement[] = []; pipeNode(node, (node, write) => emitConstructor(node, write, baseTypeNode), classMembers); - pipeNodes(node.members, visitor, classMembers); + pipeNodes(node.members, visitClassElement, classMembers); // Create the declaration for the class. Classes with decorators are transformed into a class // expression inside of a let declaration. @@ -372,7 +381,7 @@ namespace ts { */ function visitClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void): void { // Get the name of the class - let name = getDeclarationName(node); + let name = node.name || getGeneratedNameForNode(node); // Visit the base type node for the class. let baseTypeNode = mapNode(getClassExtendsHeritageClauseElement(node), visitExpressionWithTypeArguments); @@ -399,7 +408,8 @@ namespace ts { let staticProperties = getInitializedProperties(node, /*isStatic*/ true); if (staticProperties) { let expressions: Expression[] = []; - let temporaryStorage = declareLocal(); + let temporaryStorage = createTempVariable(); + hoistVariableDeclaration(temporaryStorage); expressions.push(createAssignmentExpression(temporaryStorage, classExpression)); pipeNodes(staticProperties, (member, write) => emitPropertyDeclarationExpression(member, write, node, temporaryStorage), expressions); expressions.push(temporaryStorage); @@ -409,6 +419,12 @@ namespace ts { write(classExpression); } + function visitClassElement(node: ClassElement, write: (node: ClassElement) => void): void { + if (!isConstructor(node)) { + visitor(node, write); + } + } + /** * Transforms a HeritageClause with TypeScript syntax. * @param node The HeritageClause to transform. @@ -445,17 +461,17 @@ namespace ts { * @param baseTypeNode The node for the class extends clause, if present. * @remarks This function is intended to support `transformClassLikeDeclaration` and should not be called otherwise. */ - function emitConstructor(node: ClassLikeDeclaration, write: (node: ClassElement) => void, baseTypeNode: ExpressionWithTypeArguments): void { + function emitConstructor(node: ClassExpression | ClassDeclaration, write: (node: ClassElement) => void, baseTypeNode: ExpressionWithTypeArguments): void { // Check if we have property assignment inside class declaration. // If there is a property assignment, we need to emit constructor whether users define it or not // If there is no property assignment, we can omit constructor if users do not define it let hasInstancePropertyWithInitializer = forEach(node.members, isInstancePropertyWithInitializer); - + let hasParameterPropertyAssignments = node.transformFlags & TransformFlags.ContainsParameterPropertyAssignment; let constructor = getFirstConstructorWithBody(node); // If the class does not contain nodes that require a synthesized constructor, // accept the current constructor if it exists. - if (!hasInstancePropertyWithInitializer) { + if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { if (constructor) { write(accept(constructor, visitor)); } @@ -471,6 +487,9 @@ namespace ts { else if (baseTypeNode) { parameters = [createRestParameter(createIdentifier("args"), /*location*/ undefined, NodeFlags.Generated)]; } + else { + parameters = []; + } // transform the body of the constructor let statements: Statement[] = []; @@ -488,7 +507,7 @@ namespace ts { * @param baseTypeNode The node for the class extends clause, if present. * @remarks This function is intended to be called from `emitConstructor` and should not be called otherwise. */ - function emitConstructorBody(node: ClassLikeDeclaration, write: (node: Statement) => void, constructor: ConstructorDeclaration, baseTypeNode: ExpressionWithTypeArguments) { + function emitConstructorBody(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void, constructor: ConstructorDeclaration, baseTypeNode: ExpressionWithTypeArguments) { startLexicalEnvironment(); // Emit the super call if it exists @@ -538,7 +557,7 @@ namespace ts { * @param write The callback to execute to write the result. * @param node The containing class for the property. */ - function emitPropertyDeclarationStatement(property: PropertyDeclaration, write: (node: Statement) => void, node: ClassLikeDeclaration): void { + function emitPropertyDeclarationStatement(property: PropertyDeclaration, write: (node: Statement) => void, node: ClassExpression | ClassDeclaration): void { emitPropertyDeclarationWorker(node, property, /*receiver*/ undefined, /*isExpression*/ false, write); } @@ -548,7 +567,7 @@ namespace ts { * @param write The callback to execute to write the result. * @param node The containing class for the property. */ - function emitPropertyDeclarationExpression(property: PropertyDeclaration, write: (node: Expression) => void, node: ClassLikeDeclaration, receiver: Identifier): void { + function emitPropertyDeclarationExpression(property: PropertyDeclaration, write: (node: Expression) => void, node: ClassExpression | ClassDeclaration, receiver: Identifier): void { emitPropertyDeclarationWorker(node, property, receiver, /*isExpression*/ true, write); } @@ -559,7 +578,7 @@ namespace ts { * @param writeExpression The callback to execute to write the result as an expression. * @param writeStatement The callback to execute to write the result as a statement. */ - function emitPropertyDeclarationWorker(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression, isExpression: boolean, write: (node: Expression | Statement) => void): void { + function emitPropertyDeclarationWorker(node: ClassExpression | ClassDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression, isExpression: boolean, write: (node: Expression | Statement) => void): void { let initializer = visitNode(property.initializer, visitor, isExpressionNode); if (!receiver) { @@ -581,7 +600,7 @@ namespace ts { } } - function getDecoratedClassElements(node: ClassLikeDeclaration, isStatic: boolean): ClassElement[] { + function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): ClassElement[] { let members: ClassElement[]; for (let member of node.members) { if (nodeCanBeDecorated(member) && nodeOrChildIsDecorated(member) && isStatic === ((member.flags & NodeFlags.Static) !== 0)) { @@ -601,7 +620,7 @@ namespace ts { return isPropertyDeclaration(member) && !(member.flags & NodeFlags.Static) && !!member.initializer; } - function getInitializedProperties(node: ClassLikeDeclaration, isStatic: boolean): PropertyDeclaration[] { + function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): PropertyDeclaration[] { let properties: PropertyDeclaration[]; for (let member of node.members) { if (isPropertyDeclaration(member) && isStatic === ((member.flags & NodeFlags.Static) !== 0) && member.initializer) { @@ -720,7 +739,7 @@ namespace ts { write(createFunctionDeclaration3(node.asteriskToken, node.name, parameters, body, /*location*/ node, flags)); if (thisNodeIsNamespaceExport) { - let name = getDeclarationName(node); + let name = makeSynthesized(node.name); emitNamespaceExport(name, name, write); } } @@ -1061,7 +1080,7 @@ namespace ts { return; } - let name = getDeclarationName(node); + let name = node.name; let moduleReference = convertEntityNameToExpression(visitNode(node.moduleReference, visitor, isEntityName)); if (isNamespaceLevelExport(node)) { emitNamespaceExport(node.name, moduleReference, write); @@ -1069,6 +1088,7 @@ namespace ts { else { let exportFlags = isTopLevelExport(node) ? NodeFlags.Export : undefined; write(createVariableStatement3(name, moduleReference)); + Debug.fail("not implemented"); } } @@ -1080,6 +1100,53 @@ namespace ts { || (!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node)); } + function visitBinaryExpression(node: BinaryExpression, write: (node: Expression) => void): void { + let left = visitNode(node.left, visitor, isExpressionNode); + let right = visitNode(node.right, visitor, isExpressionNode); + if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) { + // a **= b + // becomes: + // a = Math.pow(a, b) + + let target: Expression = left; + let value: Expression = left; + if (isElementAccessExpression(left)) { + // z["a"] **= b + // becomes: + // (_a = z)[_b = "a"] = Math.pow(_a[_b], b); + let expressionCache = createTempVariable(); + let expressionCacheAssignment = createAssignmentExpression(expressionCache, left.expression, left.expression); + hoistVariableDeclaration(expressionCache); + + let argumentCache = createTempVariable(); + let argumentCacheAssignment = createAssignmentExpression(argumentCache, left.argumentExpression, left.argumentExpression); + hoistVariableDeclaration(argumentCache); + + target = createElementAccessExpression2(expressionCacheAssignment, argumentCacheAssignment); + value = createElementAccessExpression2(expressionCache, argumentCache); + } + else if (isPropertyAccessExpression(left)) { + // z.a **= b + // becomes: + // (_a = z).a = Math.pow(_a.a, b) + let expressionCache = createTempVariable(); + let expressionCacheAssignment = createAssignmentExpression(expressionCache, left.expression, left.expression); + hoistVariableDeclaration(expressionCache); + + target = createPropertyAccessExpression2(expressionCacheAssignment, left.name, left); + value = createPropertyAccessExpression2(expressionCache, makeSynthesized(left.name)); + } + + write(createAssignmentExpression(target, createMathPowCall(value, right))); + } + else { + // a ** b + // becomes: + // Math.pow(a, b) + write(createMathPowCall(left, right)); + } + } + function getExpressionForPropertyName(container: Declaration): Expression { let name = container.name; if (isIdentifier(name)) { @@ -1191,6 +1258,37 @@ namespace ts { } } + function visitParenthesizedExpression(node: ParenthesizedExpression, write: (node: Expression) => void) { + // Make sure we consider all nested cast expressions, e.g.: + // (-A).x; + let expression = visitNode(node.expression, visitor, isExpressionNode); + let parentNode = getParentNode(); + if (!isArrowFunction(parentNode)) { + // We have an expression of the form: (SubExpr) + // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is. + // Omitting the parentheses, however, could cause change in the semantics of the generated + // code if the casted expression has a lower precedence than the rest of the expression, e.g.: + // (new A).foo should be emitted as (new A).foo and not new A.foo + // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString() + // new (A()) should be emitted as new (A()) and not new A() + // (function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} () + if (expression.kind !== SyntaxKind.PrefixUnaryExpression && + expression.kind !== SyntaxKind.VoidExpression && + expression.kind !== SyntaxKind.TypeOfExpression && + expression.kind !== SyntaxKind.DeleteExpression && + expression.kind !== SyntaxKind.PostfixUnaryExpression && + expression.kind !== SyntaxKind.NewExpression && + !(expression.kind === SyntaxKind.CallExpression && parentNode.kind === SyntaxKind.NewExpression) && + !(expression.kind === SyntaxKind.FunctionExpression && parentNode.kind === SyntaxKind.CallExpression) && + !(expression.kind === SyntaxKind.NumericLiteral && parentNode.kind === SyntaxKind.PropertyAccessExpression)) { + write(expression); + return; + } + } + + return updateParenthesizedExpression(node, expression); + } + function needsParenthesisForAwaitExpressionAsYield(node: AwaitExpression) { let parentNode = getParentNode(); if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { @@ -1213,7 +1311,7 @@ namespace ts { write(exportDefault); } - function emitDecoratorsOfConstructor(node: ClassLikeDeclaration, write: (node: Statement) => void) { + function emitDecoratorsOfConstructor(node: ClassExpression | ClassDeclaration, write: (node: Statement) => void) { let decorators = node.decorators; let constructor = getFirstConstructorWithBody(node); let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated); @@ -1245,7 +1343,7 @@ namespace ts { } function emitDecoratorsOfMember(member: ClassElement, write: (node: Statement) => void) { - let container = getParentNode(); + let container = getParentNode(); let decorators: Decorator[]; let method: FunctionLikeDeclaration; @@ -1525,7 +1623,8 @@ namespace ts { let result = resolver.getTypeReferenceSerializationKind(typeName); switch (result) { case TypeReferenceSerializationKind.Unknown: - let tempVar = declareLocal(); + let tempVar = createTempVariable(); + hoistVariableDeclaration(tempVar); let globalObjectName = createIdentifier("Object"); let typeExpr = serializeEntityNameAsExpression(typeName, /*useFallback*/ true); let cacheExpr = createAssignmentExpression(tempVar, typeExpr); @@ -1595,7 +1694,8 @@ namespace ts { left = serializeEntityNameAsExpression(node.left, useFallback); } else if (useFallback) { - let tempVar = declareLocal(); + let tempVar = createTempVariable(); + hoistVariableDeclaration(tempVar); let pathExpr = serializeEntityNameAsExpression(node.left, /*useFallback*/ true); let cacheExpr = createAssignmentExpression(tempVar, pathExpr); left = createLogicalAndExpression(cacheExpr, tempVar); @@ -1663,5 +1763,14 @@ namespace ts { let callExpr = createCallExpression2(createSuperKeyword(), [createSpreadElementExpression(createIdentifier("args"))]); return startOnNewLine(createExpressionStatement(callExpr, /*location*/ undefined, NodeFlags.Generated)); } + + function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) { + return node.name ? makeSynthesized(node.name) : getGeneratedNameForNode(node); + } + + function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) { + let expression = getDeclarationName(node); + return member.flags & NodeFlags.Static ? expression : createPropertyAccessExpression3(expression, "prototype"); + } } } \ No newline at end of file diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4d841b056b7..c9eccf71a64 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -330,10 +330,6 @@ namespace ts { JSDocTypeTag, JSDocTemplateTag, - // Raw nodes - RawExpression, - RawStatement, - // Synthesized list SyntaxList, // Enum value count @@ -384,6 +380,7 @@ namespace ts { ExportContext = 0x00040000, // Export context (initialized by binding) ContainsThis = 0x00080000, // Interface contains references to "this" Generated = 0x00100000, // Synthetic node generated during transformation + SingleLine = 0x00200000, // Synthetic node is single-line block. Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async, AccessibilityModifier = Public | Private | Protected, @@ -458,11 +455,11 @@ namespace ts { // @internal export interface ParentNavigator extends ParentNavigable { /** Gets the grandparent node for the current node. */ - getGrandparent(): Node; + getGrandparentNode(): Node; /** Gets the parent node for the current node. */ - getParent(): Node; + getParentNode(): Node; /** Gets the current node. */ - getNode(): Node; + getCurrentNode(): Node; /** Gets the SyntaxKind of the current node. */ getKind(): SyntaxKind; /** Moves the navigator to the parent node of the current node. */ @@ -471,12 +468,14 @@ namespace ts { // @internal export interface NodeStack extends ParentNavigable { + /** Gets the size of the stack. */ + getStackSize(): number; /** Gets the node two steps down from the top of the stack. */ - getGrandparent(): Node; + getGrandparentNode(): Node; /** Gets the node one step down from the top of the stack. */ - getParent(): Node; + getParentNode(): Node; /** Gets the node at the top of the stack. */ - getNode(): Node; + getCurrentNode(): Node; /** Gets the SyntaxKind for the node at the top of the stack. */ getKind(): SyntaxKind; /** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */ @@ -548,6 +547,7 @@ namespace ts { text: string; // Text of identifier (with escapes converted to characters) // @factoryparam originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later + tempFlags?: TempFlags; // Flags used to control temporary identifiers } // @kind(SyntaxKind.QualifiedName) @@ -585,7 +585,7 @@ namespace ts { expression: LeftHandSideExpression; } - // @kind(SyntaxKind.TypeParameter) + // @kind(SyntaxKind.TypeParameter, { create: false, update: false, test: true }) // @factoryhidden("decorators", true) // @factoryhidden("modifiers", true) export interface TypeParameterDeclaration extends Declaration { @@ -603,14 +603,14 @@ namespace ts { type?: TypeNode; } - // @kind(SyntaxKind.CallSignature) + // @kind(SyntaxKind.CallSignature, { create: false, update: false, test: false }) // @factoryhidden("name") // @factoryhidden("decorators") // @factoryhidden("modifiers") export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement { } - // @kind(SyntaxKind.ConstructSignature) + // @kind(SyntaxKind.ConstructSignature, { create: false, update: false, test: false }) // @factoryhidden("name") // @factoryhidden("decorators") // @factoryhidden("modifiers") @@ -653,7 +653,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - // @kind(SyntaxKind.PropertySignature) + // @kind(SyntaxKind.PropertySignature, { create: false, update: false, test: false }) // @factoryorder("decorators", "modifiers", "name", "questionToken", "type") export interface PropertySignature extends TypeElement { name: PropertyName; @@ -764,7 +764,7 @@ namespace ts { body?: FunctionBody; } - // @kind(SyntaxKind.MethodSignature) + // @kind(SyntaxKind.MethodSignature, { create: false, update: false, test: false }) // @factoryhidden("asteriskToken", true) // @factoryhidden("body", true) // @factoryorder("decorators", "modifiers", "asteriskToken", "name", "questionToken", "typeParameters", "parameters", "type") @@ -835,13 +835,19 @@ namespace ts { export interface SetAccessorDeclaration extends AccessorDeclaration { } - // @kind(SyntaxKind.IndexSignature) + // @kind(SyntaxKind.IndexSignature, { create: false, update: false, test: false }) // @factoryhidden("typeParameters") // @factoryhidden("name") export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement { _indexSignatureDeclarationBrand: any; } + // @kind(SyntaxKind.AnyKeyword, { create: false, update: false, test: false }) + // @kind(SyntaxKind.NumberKeyword, { create: false, update: false, test: false }) + // @kind(SyntaxKind.BooleanKeyword, { create: false, update: false, test: false }) + // @kind(SyntaxKind.StringKeyword, { create: false, update: false, test: false }) + // @kind(SyntaxKind.SymbolKeyword, { create: false, update: false, test: false }) + // @kind(SyntaxKind.VoidKeyword, { create: false, update: false, test: false }) // @nodetest("isTypeNodeNode") export interface TypeNode extends Node { _typeNodeBrand: any; @@ -851,39 +857,39 @@ namespace ts { _functionOrConstructorTypeNodeBrand: any; } - // @kind(SyntaxKind.FunctionType) + // @kind(SyntaxKind.FunctionType, { create: false, update: false, test: false }) // @factoryhidden("name") // @factoryhidden("decorators") // @factoryhidden("modifiers") export interface FunctionTypeNode extends FunctionOrConstructorTypeNode { } - // @kind(SyntaxKind.ConstructorType) + // @kind(SyntaxKind.ConstructorType, { create: false, update: false, test: false }) // @factoryhidden("name") // @factoryhidden("decorators") // @factoryhidden("modifiers") export interface ConstructorTypeNode extends FunctionOrConstructorTypeNode { } - // @kind(SyntaxKind.TypeReference) + // @kind(SyntaxKind.TypeReference, { create: false, update: false, test: true }) export interface TypeReferenceNode extends TypeNode { typeName: EntityName; typeArguments?: NodeArray; } - // @kind(SyntaxKind.TypePredicate) + // @kind(SyntaxKind.TypePredicate, { create: false, update: false, test: false }) export interface TypePredicateNode extends TypeNode { parameterName: Identifier; type: TypeNode; } - // @kind(SyntaxKind.TypeQuery) + // @kind(SyntaxKind.TypeQuery, { create: false, update: false, test: false }) export interface TypeQueryNode extends TypeNode { exprName: EntityName; } // A TypeLiteral is the declaration node for an anonymous symbol. - // @kind(SyntaxKind.TypeLiteral) + // @kind(SyntaxKind.TypeLiteral, { create: false, update: false, test: false }) // @factoryhidden("name", true) // @factoryhidden("decorators", true) // @factoryhidden("modifiers", true) @@ -891,12 +897,12 @@ namespace ts { members: NodeArray; } - // @kind(SyntaxKind.ArrayType) + // @kind(SyntaxKind.ArrayType, { create: false, update: false, test: true }) export interface ArrayTypeNode extends TypeNode { elementType: TypeNode; } - // @kind(SyntaxKind.TupleType) + // @kind(SyntaxKind.TupleType, { create: false, update: false, test: false }) export interface TupleTypeNode extends TypeNode { elementTypes: NodeArray; } @@ -905,13 +911,13 @@ namespace ts { types: NodeArray; } - // @kind(SyntaxKind.UnionType) + // @kind(SyntaxKind.UnionType, { create: false, update: false, test: false }) export interface UnionTypeNode extends UnionOrIntersectionTypeNode { } - // @kind(SyntaxKind.IntersectionType) + // @kind(SyntaxKind.IntersectionType, { create: false, update: false, test: false }) export interface IntersectionTypeNode extends UnionOrIntersectionTypeNode { } - // @kind(SyntaxKind.ParenthesizedType) + // @kind(SyntaxKind.ParenthesizedType, { create: false, update: false, test: false }) export interface ParenthesizedTypeNode extends TypeNode { type: TypeNode; } @@ -938,9 +944,6 @@ namespace ts { // @kind(SyntaxKind.OmittedExpression) export interface OmittedExpression extends Expression { } - // @kind(SyntaxKind.RawExpression) - export interface RawExpression extends LiteralExpression { } - export interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } @@ -975,36 +978,36 @@ namespace ts { _memberExpressionBrand: any; } - // @kind(SyntaxKind.TrueKeyword) - // @kind(SyntaxKind.FalseKeyword) - // @kind(SyntaxKind.NullKeyword) - // @kind(SyntaxKind.ThisKeyword) - // @kind(SyntaxKind.SuperKeyword) + // @kind(SyntaxKind.TrueKeyword, { update: false, test: false }) + // @kind(SyntaxKind.FalseKeyword, { update: false, test: false }) + // @kind(SyntaxKind.NullKeyword, { update: false, test: false }) + // @kind(SyntaxKind.ThisKeyword, { update: false }) + // @kind(SyntaxKind.SuperKeyword, { update: false }) export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } - // @kind(SyntaxKind.DeleteExpression) + // @kind(SyntaxKind.DeleteExpression, { test: false }) export interface DeleteExpression extends UnaryExpression { expression: UnaryExpression; } - // @kind(SyntaxKind.TypeOfExpression) + // @kind(SyntaxKind.TypeOfExpression, { test: false }) export interface TypeOfExpression extends UnaryExpression { expression: UnaryExpression; } - // @kind(SyntaxKind.VoidExpression) + // @kind(SyntaxKind.VoidExpression, { test: false }) export interface VoidExpression extends UnaryExpression { expression: UnaryExpression; } - // @kind(SyntaxKind.AwaitExpression) + // @kind(SyntaxKind.AwaitExpression, { test: false }) export interface AwaitExpression extends UnaryExpression { expression: UnaryExpression; } - // @kind(SyntaxKind.YieldExpression) + // @kind(SyntaxKind.YieldExpression, { test: false }) export interface YieldExpression extends Expression { // @factoryparam asteriskToken?: Node; @@ -1058,11 +1061,11 @@ namespace ts { // or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters. // For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1". // @kind(SyntaxKind.NumericLiteral) - // @kind(SyntaxKind.RegularExpressionLiteral) + // @kind(SyntaxKind.RegularExpressionLiteral, { test: false }) // @kind(SyntaxKind.NoSubstitutionTemplateLiteral) - // @kind(SyntaxKind.TemplateHead) - // @kind(SyntaxKind.TemplateMiddle) - // @kind(SyntaxKind.TemplateTail) + // @kind(SyntaxKind.TemplateHead, { test: false }) + // @kind(SyntaxKind.TemplateMiddle, { test: false }) + // @kind(SyntaxKind.TemplateTail, { test: false }) export interface LiteralExpression extends PrimaryExpression { // @factoryparam text: string; @@ -1183,7 +1186,7 @@ namespace ts { /// Either the opening tag in a ... pair, or the lone in a self-closing form export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; - // @kind(SyntaxKind.JsxAttribute) + // @kind(SyntaxKind.JsxAttribute, { test: false }) export interface JsxAttribute extends Node { name: Identifier; /// JSX attribute initializers are optional; is sugar for @@ -1217,19 +1220,13 @@ namespace ts { _statementBrand: any; } - // @kind(SyntaxKind.RawStatement) - export interface RawStatement extends Statement { - // @factoryparam - text: string; - } - - // @kind(SyntaxKind.EmptyStatement) + // @kind(SyntaxKind.EmptyStatement, { test: false }) export interface EmptyStatement extends Statement { } - // @kind(SyntaxKind.DebuggerStatement) + // @kind(SyntaxKind.DebuggerStatement, { test: false }) export interface DebuggerStatement extends Statement { } - // @kind(SyntaxKind.MissingDeclaration) + // @kind(SyntaxKind.MissingDeclaration, { create: false, update: false, test: false }) // @factoryhidden("name", true) export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { name?: Identifier; @@ -1242,7 +1239,7 @@ namespace ts { statements: NodeArray; } - // @kind(SyntaxKind.VariableStatement) + // @kind(SyntaxKind.VariableStatement, { test: false }) // @factoryhidden("decorators", false) // @factoryhidden("modifiers", false) export interface VariableStatement extends Statement { @@ -1295,12 +1292,12 @@ namespace ts { expression: Expression; } - // @kind(SyntaxKind.BreakStatement) + // @kind(SyntaxKind.BreakStatement, { test: false }) export interface BreakStatement extends Statement { label?: Identifier; } - // @kind(SyntaxKind.ContinueStatement) + // @kind(SyntaxKind.ContinueStatement, { test: false }) export interface ContinueStatement extends Statement { label?: Identifier; } @@ -1312,13 +1309,13 @@ namespace ts { expression?: Expression; } - // @kind(SyntaxKind.WithStatement) + // @kind(SyntaxKind.WithStatement, { test: false }) export interface WithStatement extends Statement { expression: Expression; statement: Statement; } - // @kind(SyntaxKind.SwitchStatement) + // @kind(SyntaxKind.SwitchStatement, { test: false }) export interface SwitchStatement extends Statement { expression: Expression; caseBlock: CaseBlock; @@ -1329,31 +1326,31 @@ namespace ts { clauses: NodeArray; } - // @kind(SyntaxKind.CaseClause) + // @kind(SyntaxKind.CaseClause, { test: false }) export interface CaseClause extends Node { expression?: Expression; statements: NodeArray; } - // @kind(SyntaxKind.DefaultClause) + // @kind(SyntaxKind.DefaultClause, { test: false }) export interface DefaultClause extends Node { statements: NodeArray; } export type CaseOrDefaultClause = CaseClause | DefaultClause; - // @kind(SyntaxKind.LabeledStatement) + // @kind(SyntaxKind.LabeledStatement, { test: false }) export interface LabeledStatement extends Statement { label: Identifier; statement: Statement; } - // @kind(SyntaxKind.ThrowStatement) + // @kind(SyntaxKind.ThrowStatement, { test: false }) export interface ThrowStatement extends Statement { expression: Expression; } - // @kind(SyntaxKind.TryStatement) + // @kind(SyntaxKind.TryStatement, { test: false }) export interface TryStatement extends Statement { tryBlock: Block; catchClause?: CatchClause; @@ -1397,7 +1394,7 @@ namespace ts { questionToken?: Node; } - // @kind(SyntaxKind.InterfaceDeclaration) + // @kind(SyntaxKind.InterfaceDeclaration, { create: false, update: false, test: false }) export interface InterfaceDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; @@ -1412,7 +1409,7 @@ namespace ts { types?: NodeArray; } - // @kind(SyntaxKind.TypeAliasDeclaration) + // @kind(SyntaxKind.TypeAliasDeclaration, { create: false, update: false, test: false }) export interface TypeAliasDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; @@ -1429,7 +1426,7 @@ namespace ts { initializer?: Expression; } - // @kind(SyntaxKind.EnumDeclaration) + // @kind(SyntaxKind.EnumDeclaration, { test: false }) export interface EnumDeclaration extends DeclarationStatement { name: Identifier; members: NodeArray; @@ -1457,7 +1454,7 @@ namespace ts { moduleReference: EntityName | ExternalModuleReference; } - // @kind(SyntaxKind.ExternalModuleReference) + // @kind(SyntaxKind.ExternalModuleReference, { test: false }) export interface ExternalModuleReference extends Node { expression?: Expression; } @@ -1549,68 +1546,69 @@ namespace ts { } // represents a top level: { type } expression in a JSDoc comment. - // @kind(SyntaxKind.JSDocTypeExpression) + // @kind(SyntaxKind.JSDocTypeExpression, { create: false, update: false, test: false }) export interface JSDocTypeExpression extends Node { type: JSDocType; } + // @nodetest(null) export interface JSDocType extends TypeNode { _jsDocTypeBrand: any; } - // @kind(SyntaxKind.JSDocAllType) + // @kind(SyntaxKind.JSDocAllType, { create: false, update: false, test: false }) export interface JSDocAllType extends JSDocType { _JSDocAllTypeBrand: any; } - // @kind(SyntaxKind.JSDocUnknownType) + // @kind(SyntaxKind.JSDocUnknownType, { create: false, update: false, test: false }) export interface JSDocUnknownType extends JSDocType { _JSDocUnknownTypeBrand: any; } - // @kind(SyntaxKind.JSDocArrayType) + // @kind(SyntaxKind.JSDocArrayType, { create: false, update: false, test: false }) export interface JSDocArrayType extends JSDocType { elementType: JSDocType; } - // @kind(SyntaxKind.JSDocUnionType) + // @kind(SyntaxKind.JSDocUnionType, { create: false, update: false, test: false }) export interface JSDocUnionType extends JSDocType { types: NodeArray; } - // @kind(SyntaxKind.JSDocTupleType) + // @kind(SyntaxKind.JSDocTupleType, { create: false, update: false, test: false }) export interface JSDocTupleType extends JSDocType { types: NodeArray; } - // @kind(SyntaxKind.JSDocNonNullableType) + // @kind(SyntaxKind.JSDocNonNullableType, { create: false, update: false, test: false }) export interface JSDocNonNullableType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocNullableType) + // @kind(SyntaxKind.JSDocNullableType, { create: false, update: false, test: false }) export interface JSDocNullableType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocRecordType) + // @kind(SyntaxKind.JSDocRecordType, { create: false, update: false, test: false }) // @factoryhidden("name", true) export interface JSDocRecordType extends JSDocType, TypeLiteralNode { members: NodeArray; } - // @kind(SyntaxKind.JSDocTypeReference) + // @kind(SyntaxKind.JSDocTypeReference, { create: false, update: false, test: false }) export interface JSDocTypeReference extends JSDocType { name: EntityName; typeArguments: NodeArray; } - // @kind(SyntaxKind.JSDocOptionalType) + // @kind(SyntaxKind.JSDocOptionalType, { create: false, update: false, test: false }) export interface JSDocOptionalType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocFunctionType) + // @kind(SyntaxKind.JSDocFunctionType, { create: false, update: false, test: false }) // @factoryhidden("name", true) // @factoryhidden("typeParameters", true) // @factoryhidden("decorators", true) @@ -1620,22 +1618,22 @@ namespace ts { type: JSDocType; } - // @kind(SyntaxKind.JSDocVariadicType) + // @kind(SyntaxKind.JSDocVariadicType, { create: false, update: false, test: false }) export interface JSDocVariadicType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocConstructorType) + // @kind(SyntaxKind.JSDocConstructorType, { create: false, update: false, test: false }) export interface JSDocConstructorType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocThisType) + // @kind(SyntaxKind.JSDocThisType, { create: false, update: false, test: false }) export interface JSDocThisType extends JSDocType { type: JSDocType; } - // @kind(SyntaxKind.JSDocRecordMember) + // @kind(SyntaxKind.JSDocRecordMember, { create: false, update: false, test: false }) // @factoryhidden("questionToken", true) // @factoryhidden("initializer", true) // @factoryhidden("decorators", true) @@ -1645,34 +1643,34 @@ namespace ts { type?: JSDocType; } - // @kind(SyntaxKind.JSDocComment) + // @kind(SyntaxKind.JSDocComment, { create: false, update: false, test: false }) export interface JSDocComment extends Node { tags: NodeArray; } - // @kind(SyntaxKind.JSDocTag) + // @kind(SyntaxKind.JSDocTag, { create: false, update: false, test: false }) export interface JSDocTag extends Node { // @factoryparam atToken: Node; tagName: Identifier; } - // @kind(SyntaxKind.JSDocTemplateTag) + // @kind(SyntaxKind.JSDocTemplateTag, { create: false, update: false, test: false }) export interface JSDocTemplateTag extends JSDocTag { typeParameters: NodeArray; } - // @kind(SyntaxKind.JSDocReturnTag) + // @kind(SyntaxKind.JSDocReturnTag, { create: false, update: false, test: false }) export interface JSDocReturnTag extends JSDocTag { typeExpression: JSDocTypeExpression; } - // @kind(SyntaxKind.JSDocTypeTag) + // @kind(SyntaxKind.JSDocTypeTag, { create: false, update: false, test: false }) export interface JSDocTypeTag extends JSDocTag { typeExpression: JSDocTypeExpression; } - // @kind(SyntaxKind.JSDocParameterTag) + // @kind(SyntaxKind.JSDocParameterTag, { create: false, update: false, test: false }) export interface JSDocParameterTag extends JSDocTag { preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; @@ -2875,16 +2873,27 @@ namespace ts { * - Constructor Parameters with accessibility modifiers. * - Decorators */ - ContainerIsTypeScript = 1 << 16, - ContainerIsES6 = 1 << 17, - ContainsLexicalThis = 1 << 18, - ContainsCapturedLexicalThis = 1 << 19, - ContainsDefaultValueAssignments = 1 << 20, + ContainerIsTypeScript = 1 << 8, + ContainsDecorator = 1 << 9, + ContainsPropertyInitializer = 1 << 10, + ContainsLexicalThis = 1 << 11, + ContainsCapturedLexicalThis = 1 << 12, + ContainsDefaultValueAssignments = 1 << 13, + ContainsParameterPropertyAssignment = 1 << 14, - // ContainsES6Yield = 1 << 20, - // ContainsES6SpreadElement = 1 << 21, - // ContainsES6LetOrConst = 1 << 22, - // ContainsES6ComputedPropertyName = 1 << 23, + /** + * Indicates a parent ArrayLiteralExpression, CallExpression, or NewExpression contains + * a SpreadElementExpression. Those nodes should exclude this flag so that it is not + * aggregated further up the tree. + */ + ContainsSpreadElementExpression = 1 << 15, + + /** + * Indicates a parent ObjectLiteralExpression, ClassDeclaration, or ClassExpression + * contains a ComputedPropertyName. Those nodes should exlcude this flag so that it is not + * aggregated further up the tree. + */ + ContainsComputedPropertyName = 1 << 16, // // Assertions @@ -2936,6 +2945,11 @@ namespace ts { // ContainsES6RestParameter | // ContainsCapturedThis, + TypeScriptClassSyntaxExtensionsMask = + ContainsParameterPropertyAssignment | + ContainsPropertyInitializer | + ContainsDecorator, + // // Scope Exclusions // @@ -2947,16 +2961,18 @@ namespace ts { ArrowFunctionExcludes = ContainerIsTypeScript | - ContainerIsES6 | + ContainsDecorator | ContainsDefaultValueAssignments | - ContainsLexicalThis, + ContainsLexicalThis | + ContainsParameterPropertyAssignment, FunctionDeclarationOrExpressionExcludes = ContainerIsTypeScript | - ContainerIsES6 | + ContainsDecorator | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | - ContainsLexicalThis, + ContainsLexicalThis | + ContainsParameterPropertyAssignment, ConstructorExcludes = ContainsDefaultValueAssignments | @@ -2966,26 +2982,40 @@ namespace ts { MethodDeclarationExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | - ContainsCapturedLexicalThis, + ContainsCapturedLexicalThis | + ContainsParameterPropertyAssignment, GetOrSetAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | - ContainsCapturedLexicalThis, + ContainsCapturedLexicalThis | + ContainsParameterPropertyAssignment, ClassDeclarationOrExpressionExcludes = ContainerIsTypeScript | + ContainsDecorator | + ContainsPropertyInitializer | ContainsLexicalThis | - ContainsCapturedLexicalThis, + ContainsCapturedLexicalThis | + ContainsComputedPropertyName | + ContainsParameterPropertyAssignment, ModuleScopeExcludes = ContainerIsTypeScript | + ContainsDecorator | ContainsLexicalThis | ContainsCapturedLexicalThis, TypeExcludes = ~ContainsTypeScript, + ObjectLiteralExpressionExcludes = + ContainsDecorator | + ContainsComputedPropertyName, + + ArrayLiteralOrCallOrNewExpressionExcludes = + ContainsSpreadElementExpression, + // CallOrArrayLiteralExcludes = // ContainsES6SpreadElement, } @@ -2998,18 +3028,6 @@ namespace ts { // @internal export type Transformation = (node: SourceFile) => SourceFile; - // @internal - export interface TransformationSubstitutions { - getGeneratedNodeFlags(node: Node): GeneratedNodeFlags; - expressionSubstitution: (node: Expression) => Expression; - } - - // @internal - export interface TransformationResult { - sourceFiles: SourceFile[]; - substitutions?: TransformationSubstitutions; - } - // @internal export const enum GeneratedNodeFlags { EmitHelpers = 1 << 0, @@ -3024,10 +3042,9 @@ namespace ts { getCompilerOptions(): CompilerOptions; /** - * Generates a name unique to the source file given the provided base. - * @param baseName The base name. + * Gets a value indicating whether the specified text is unique. */ - makeUniqueName(baseName: string): string; + isUniqueName(text: string): boolean; /** * Generates and caches a name unique to the node within the current lexical environment. @@ -3053,16 +3070,16 @@ namespace ts { */ createTempVariable(flags?: TempFlags): Identifier; - /** - * Creates a temporary variable using an optional base name and records it - * within the current lexical environment. - * - * This is the equivalent of: - * hoistVariableDeclaration(baseName ? createUniqueIdentifier(baseName) : createTempVariable()); - * - * @param baseName An optional base name for the temporary variable. - */ - declareLocal(baseName?: string): Identifier; + // /** + // * Creates a temporary variable using an optional base name and records it + // * within the current lexical environment. + // * + // * This is the equivalent of: + // * hoistVariableDeclaration(baseName ? createUniqueIdentifier(baseName) : createTempVariable()); + // * + // * @param baseName An optional base name for the temporary variable. + // */ + // declareLocal(baseName?: string): Identifier; /** * Hoists the name of a variable declaration within a lexical environment. @@ -3083,7 +3100,7 @@ namespace ts { hoistFunctionDeclaration(func: FunctionDeclaration): void; createParentNavigator(): ParentNavigator; // from NodeStack - getRootNode(): SourceFile; // from NodeStack + getSourceFile(): SourceFile; // from NodeStack getParentNode(): Node; // from NodeStack getCurrentNode(): Node; // from NodeStack tryPushNode(node: Node): boolean; // from NodeStack @@ -3093,21 +3110,24 @@ namespace ts { findAncestorNode(match: (node: Node) => node is T): T; // from NodeStack findAncestorNode(match: (node: Node) => boolean): Node; // from NodeStack - // @deprecated - getDeclarationName(node: DeclarationStatement): Identifier; + // // @deprecated + // getDeclarationName(node: DeclarationStatement): Identifier; - // @deprecated - getDeclarationName(node: ClassLikeDeclaration): Identifier; + // // @deprecated + // getDeclarationName(node: ClassLikeDeclaration): Identifier; - // @deprecated - getDeclarationName(node: Declaration): DeclarationName; + // // @deprecated + // getDeclarationName(node: Declaration): DeclarationName; - // @deprecated - getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement): LeftHandSideExpression; + // // @deprecated + // getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement): LeftHandSideExpression; setGeneratedNodeFlags(node: Node, flags: GeneratedNodeFlags): void; getGeneratedNodeFlags(node: Node): GeneratedNodeFlags; + setBindingIdentifierSubstitution(substitution: (node: Identifier) => Identifier): void; + getBindingIdentifierSubstitution(): (node: Identifier) => Identifier; + /** * Rather than recurse deeply into a syntax tree to rewrite identifiers for exports * or block-scoped declarations, you can establish a general substitution function to use diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f87106d3e93..9f30968b16e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -255,7 +255,7 @@ namespace ts { export function getEnclosingBlockScopeContainer(navigable: ParentNavigable): Node { let nav = navigable.createParentNavigator(); while (nav.moveToParent()) { - let current = nav.getNode(); + let current = nav.getCurrentNode(); if (isFunctionLike(current)) { return current; } @@ -271,7 +271,7 @@ namespace ts { case SyntaxKind.Block: // function block is not considered block-scope container // see comment in binder.ts: bind(...), case for SyntaxKind.Block - if (!isFunctionLike(nav.getParent())) { + if (!isFunctionLike(nav.getParentNode())) { return current; } } @@ -376,19 +376,19 @@ namespace ts { /** Returns the node flags for this node and all relevant parent nodes. */ export function getCombinedNodeFlags(navigable: ParentNavigable): NodeFlags { let nav = navigable.createParentNavigator(); - let node = nav.getNode(); + let node = nav.getCurrentNode(); while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) { - node = nav.moveToParent() ? nav.getNode() : undefined; + node = nav.moveToParent() ? nav.getCurrentNode() : undefined; } let flags = node.flags; if (node.kind === SyntaxKind.VariableDeclaration) { - node = nav.moveToParent() ? nav.getNode() : undefined; + node = nav.moveToParent() ? nav.getCurrentNode() : undefined; } if (node && node.kind === SyntaxKind.VariableDeclarationList) { flags |= node.flags; - node = nav.moveToParent() ? nav.getNode() : undefined; + node = nav.moveToParent() ? nav.getCurrentNode() : undefined; } if (node && node.kind === SyntaxKind.VariableStatement) { @@ -685,7 +685,7 @@ namespace ts { export function getContainingFunction(navigable: ParentNavigable): FunctionLikeDeclaration { let nav = navigable.createParentNavigator(); while (nav.moveToParent()) { - let node = nav.getNode(); + let node = nav.getCurrentNode(); if (isFunctionLike(node)) { return node; } @@ -697,7 +697,7 @@ namespace ts { export function getContainingClass(navigable: ParentNavigable): ClassLikeDeclaration { let nav = navigable.createParentNavigator(); while (nav.moveToParent()) { - let node = nav.getNode(); + let node = nav.getCurrentNode(); if (isClassLike(node)) { return node; } @@ -709,14 +709,14 @@ namespace ts { export function getThisContainer(navigable: ParentNavigable, includeArrowFunctions: boolean): Node { let nav = navigable.createParentNavigator(); while (nav.moveToParent()) { - let node = nav.getNode(); + let node = nav.getCurrentNode(); switch (node.kind) { case SyntaxKind.ComputedPropertyName: // If the grandparent node is an object literal (as opposed to a class), // then the computed property is not a 'this' container. // A computed property name in a class needs to be a this container // so that we can error on it. - if (isClassLike(nav.getGrandparent())) { + if (isClassLike(nav.getGrandparentNode())) { return node; } // If this is a computed property, then the parent should not @@ -728,13 +728,13 @@ namespace ts { break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. - if (isParameter(nav.getParent()) && isClassElement(nav.getGrandparent())) { + if (isParameter(nav.getParentNode()) && isClassElement(nav.getGrandparentNode())) { // If the decorator's parent is a Parameter, we resolve the this container from // the grandparent class declaration. nav.moveToParent(); nav.moveToParent(); } - else if (isClassElement(nav.getParent())) { + else if (isClassElement(nav.getParentNode())) { // If the decorator's parent is a class element, we resolve the 'this' container // from the parent class declaration. nav.moveToParent(); @@ -768,14 +768,14 @@ namespace ts { export function getSuperContainer(navigable: ParentNavigable, includeFunctions: boolean): Node { let nav = navigable.createParentNavigator(); while (nav.moveToParent()) { - let node = nav.getNode(); + let node = nav.getCurrentNode(); switch (node.kind) { case SyntaxKind.ComputedPropertyName: // If the grandparent node is an object literal (as opposed to a class), // then the computed property is not a 'super' container. // A computed property name in a class needs to be a super container // so that we can error on it. - if (isClassLike(nav.getGrandparent())) { + if (isClassLike(nav.getGrandparentNode())) { return node; } // If this is a computed property, then the parent should not @@ -787,14 +787,14 @@ namespace ts { break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. - if (isParameter(nav.getParent()) - && isClassElement(nav.getGrandparent())) { + if (isParameter(nav.getParentNode()) + && isClassElement(nav.getGrandparentNode())) { // If the decorator's parent is a Parameter, we resolve the this container from // the grandparent class declaration. nav.moveToParent(); nav.moveToParent(); } - else if (isClassElement(nav.getParent())) { + else if (isClassElement(nav.getParentNode())) { // If the decorator's parent is a class element, we resolve the 'this' container // from the parent class declaration. nav.moveToParent(); @@ -854,7 +854,7 @@ namespace ts { export function nodeCanBeDecorated(navigable: ParentNavigable): boolean { let nav = navigable.createParentNavigator(); - let node = nav.getNode(); + let node = nav.getCurrentNode(); switch (node.kind) { case SyntaxKind.ClassDeclaration: // classes are valid targets @@ -862,17 +862,17 @@ namespace ts { case SyntaxKind.PropertyDeclaration: // property declarations are valid if their parent is a class declaration. - return nav.getParent().kind === SyntaxKind.ClassDeclaration; + return nav.getParentNode().kind === SyntaxKind.ClassDeclaration; case SyntaxKind.Parameter: // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target; - return (nav.getParent()).body && nav.getGrandparent().kind === SyntaxKind.ClassDeclaration; + return (nav.getParentNode()).body && nav.getGrandparentNode().kind === SyntaxKind.ClassDeclaration; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: // if this method has a body and its parent is a class declaration, this is a valid target. - return (node).body && nav.getParent().kind === SyntaxKind.ClassDeclaration; + return (node).body && nav.getParentNode().kind === SyntaxKind.ClassDeclaration; } return false; @@ -935,7 +935,7 @@ namespace ts { export function isExpression(navigable: ParentNavigable): boolean { let nav = navigable.createParentNavigator(); while (true) { - let node = nav.getNode(); + let node = nav.getCurrentNode(); switch (node.kind) { case SyntaxKind.SuperKeyword: case SyntaxKind.NullKeyword: @@ -981,7 +981,7 @@ namespace ts { return nav.getKind() === SyntaxKind.TypeQuery; case SyntaxKind.Identifier: - if (nav.getParent().kind === SyntaxKind.TypeQuery) { + if (nav.getParentNode().kind === SyntaxKind.TypeQuery) { return true; } @@ -990,7 +990,7 @@ namespace ts { case SyntaxKind.StringLiteral: case SyntaxKind.ThisKeyword: nav.moveToParent(); - let parent = nav.getNode(); + let parent = nav.getCurrentNode(); switch (parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: @@ -2381,8 +2381,8 @@ namespace ts { export function isExpressionWithTypeArgumentsInClassExtendsClause(navigable: ParentNavigable): boolean { let nav = navigable.createParentNavigator(); if (nav.getKind() === SyntaxKind.ExpressionWithTypeArguments) { - if ((nav.getParent()).token === SyntaxKind.ExtendsKeyword) { - return isClassLike(nav.getGrandparent()); + if ((nav.getParentNode()).token === SyntaxKind.ExtendsKeyword) { + return isClassLike(nav.getGrandparentNode()); } } return false;