diff --git a/Jakefile.js b/Jakefile.js index e3a96d9f25d..d20ada3a6ad 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -44,6 +44,7 @@ var compilerSources = [ "transform.ts", "transform.generated.ts", "transforms/es6.ts", + "transforms/es5.ts", "declarationEmitter.ts", "emitter.ts", "program.ts", @@ -66,6 +67,7 @@ var servicesSources = [ "transform.ts", "transform.generated.ts", "transforms/es6.ts", + "transforms/es5.ts", "declarationEmitter.ts", "emitter.ts", "program.ts", @@ -209,6 +211,7 @@ function concatenateFiles(destinationFile, sourceFiles) { } var useDebugMode = true; +var useTransforms = false; var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node"); var compilerFilename = "tsc.js"; /* Compiles a file from a list of sources @@ -236,7 +239,9 @@ function compileFile(outFile, sources, prereqs, opts, callback) { , noResolve = opts && opts.noResolve , stripInternal = opts && opts.stripInternal , experimentalDecorators = opts && opts.experimentalDecorators - , target = opts && opts.target; + , experimentalTransforms = opts && opts.experimentalTransforms + , target = opts && opts.target + , diagnostics = opts && opts.diagnostics; var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory; var options = "--module commonjs -noImplicitAny"; @@ -279,9 +284,17 @@ function compileFile(outFile, sources, prereqs, opts, callback) { options += " --experimentalDecorators"; } + if (experimentalTransforms || (useBuiltCompiler && useTransforms)) { + options += " --experimentalTransforms"; + } + if (target) { options += " --target " + target; } + + if (diagnostics) { + options += " --diagnostics"; + } var cmd = host + " " + dir + compilerFilename + " " + options + " "; cmd = cmd + sources.join(" "); @@ -444,6 +457,10 @@ task("setDebugMode", function() { useDebugMode = true; }); +task("setTransforms", function() { + useTransforms = true; +}); + task("configure-nightly", [configureNightlyJs], function() { var cmd = "node " + configureNightlyJs + " " + packageJson + " " + programTs; console.log(cmd); @@ -478,7 +495,7 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc preserveConstEnums: true, keepComments: true, noResolve: false, - stripInternal: true, + stripInternal: true }, /*callback*/ function () { jake.cpR(servicesFile, nodePackageFile, {silent: true}); @@ -491,7 +508,6 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc fs.writeFileSync(nodeDefinitionsFile, definitionFileContents); }); - var serverFile = path.join(builtLocalDirectory, "tsserver.js"); compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), { prefixes: [copyright], @@ -590,7 +606,15 @@ directory(builtLocalDirectory); // Task to build the tests infrastructure using the built compiler var run = path.join(builtLocalDirectory, "run.js"); compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), { - useBuiltCompiler: true + useBuiltCompiler: true, + diagnostics: true +}); + +var run2 = path.join(builtLocalDirectory, "run-tx.js"); +compileFile(run2, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), { + useBuiltCompiler: true, + experimentalTransforms: true, + diagnostics: true }); var internalTests = "internal/"; @@ -607,6 +631,9 @@ var refTest262Baseline = path.join(internalTests, "baselines/test262/reference") desc("Builds the test infrastructure using the built compiler"); task("tests", ["local", run].concat(libraryTargets)); +// Temporary task created to compare transform output on typescriptServices.js +task("tx", ["generate-diagnostics", "generate-factory", "lib", tscFile, run, run2]); + function exec(cmd, completeHandler, errorHandler) { var ex = jake.createExec([cmd], {windowsVerbatimArguments: true}); // Add listeners for output and error diff --git a/scripts/processTypes.ts b/scripts/processTypes.ts index 9f91ef3749d..f4684d7297c 100644 --- a/scripts/processTypes.ts +++ b/scripts/processTypes.ts @@ -752,44 +752,44 @@ function generateTransform(outputFile: string) { sys.writeFile(outputFile, writer.getText()); function writeVisitNodesFunctions() { - for (let typeName in memberTypeUsages) { - if (hasProperty(memberTypeUsages, typeName)) { - writeVisitNodeFunction(typeName); - } - } - for (let typeName in nodeArrayTypeUsages) { - if (getProperty(nodeArrayTypeUsages, typeName)) { - writeVisitNodesFunction(typeName); - } - } + // for (let typeName in memberTypeUsages) { + // if (hasProperty(memberTypeUsages, typeName)) { + // writeVisitNodeFunction(typeName); + // } + // } + // for (let typeName in nodeArrayTypeUsages) { + // if (getProperty(nodeArrayTypeUsages, typeName)) { + // writeVisitNodesFunction(typeName); + // } + // } } function writeVisitNodeFunction(typeName: string) { - if (typeName === "Node") { - return; - } + // if (typeName === "Node") { + // return; + // } - // Skip the visit function for this node if it is defined in transform.ts - if (resolveQualifiedName(transformSourceFile, `ts.transform.visit${typeNameToMethodNameSuffix(typeName)}`, SymbolFlags.Function)) { - return; - } + // // Skip the visit function for this node if it is defined in transform.ts + // if (resolveQualifiedName(transformSourceFile, `ts.transform.visit${typeNameToMethodNameSuffix(typeName)}`, SymbolFlags.Function)) { + // return; + // } - writer.write(`export function visit${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, node: ${typeName}, visitor: Visitor): ${typeName} {`); - writer.writeLine(); - writer.increaseIndent(); + // writer.write(`export function visit${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, node: ${typeName}, visitor: Visitor, mutator?: NodeWriter<${typeName}>): ${typeName} {`); + // writer.writeLine(); + // writer.increaseIndent(); - writer.write(`let visited = visit(context, node, visitor);`); - writer.writeLine(); + // writer.write(`let visited = visit(context, node, visitor, mutator);`); + // writer.writeLine(); - writer.write(`Debug.assert(!visited || is${typeNameToMethodNameSuffix(typeName)}(visited), "Wrong node kind after visit.");`); - writer.writeLine(); + // writer.write(`Debug.assert(!visited || is${typeNameToMethodNameSuffix(typeName)}(visited), "Wrong node kind after visit.");`); + // writer.writeLine(); - writer.write(`return <${typeName}>visited;`); - writer.writeLine(); + // writer.write(`return <${typeName}>visited;`); + // writer.writeLine(); - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); + // writer.decreaseIndent(); + // writer.write(`}`); + // writer.writeLine(); } function writeVisitNodesFunction(typeName: string) { @@ -802,7 +802,7 @@ function generateTransform(outputFile: string) { return; } - writer.write(`export function visitNodeArrayOf${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, nodes: Array<${typeName}>, visitor: Visitor): NodeArray<${typeName}> {`); + writer.write(`export function visitNodeArrayOf${typeNameToMethodNameSuffix(typeName)}(context: VisitorContext, nodes: Array<${typeName}>, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): NodeArray<${typeName}> {`); writer.writeLine(); writer.increaseIndent(); @@ -815,15 +815,15 @@ function generateTransform(outputFile: string) { } function writeAcceptFunction() { - writer.write(`export function accept(context: VisitorContext, node: Node, visitor: Visitor): Node {`); + writer.write(`export function accept(context: VisitorContext, node: Node, visitor: Visitor, write: (node: Node) => void): void {`); writer.writeLine(); writer.increaseIndent(); - writer.write(`if (!node || !visitor) {`); + writer.write(`if (!node) {`); writer.writeLine(); writer.increaseIndent(); - writer.write(`return node;`); + writer.write(`return;`); writer.writeLine(); writer.decreaseIndent(); @@ -843,7 +843,7 @@ function generateTransform(outputFile: string) { writer.writeLine(); writer.increaseIndent(); - writer.write(`return factory.update${syntaxNode.kindName}(`); + writer.write(`return write(factory.update${syntaxNode.kindName}(`); writer.writeLine(); writer.increaseIndent(); writer.write(`<${syntaxNode.typeName}>node`); @@ -855,15 +855,26 @@ function generateTransform(outputFile: string) { writer.write(`, `); writer.writeLine(); - let visitorFunction = - member.visitorFunction ? member.visitorFunction : - member.isNodeArray || member.isModifiersArray ? `visitNodeArrayOf${typeNameToMethodNameSuffix(member.elementTypeName)}` : - `visit${typeNameToMethodNameSuffix(member.typeName)}`; - writer.write(`${visitorFunction}(context, (<${syntaxNode.typeName}>node).${member.propertyName}, visitor)`); + if (member.typeName === "Node") { + writer.write(`(<${syntaxNode.typeName}>node).${member.propertyName}`); + } + else { + // let visitorFunction = + // member.visitorFunction ? member.visitorFunction : + // member.isNodeArray || member.isModifiersArray ? `visitNodeArrayOf${typeNameToMethodNameSuffix(member.elementTypeName)}` : + // `visit${typeNameToMethodNameSuffix(member.typeName)}`; + + let visitorFunction = + member.visitorFunction ? member.visitorFunction : + member.isNodeArray || member.isModifiersArray ? `>visitNodes` : + `<${member.typeName}>visitNode`; + + writer.write(`${visitorFunction}(context, (<${syntaxNode.typeName}>node).${member.propertyName}, visitor)`); + } } - writer.write(`);`); + writer.write(`));`); writer.writeLine(); writer.decreaseIndent(); writer.decreaseIndent(); @@ -872,7 +883,7 @@ function generateTransform(outputFile: string) { writer.write(`default:`); writer.writeLine(); writer.increaseIndent(); - writer.write(`return node;`); + writer.write(`return write(node);`); writer.writeLine(); writer.decreaseIndent(); writer.decreaseIndent(); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3363987322a..3f0394fc82b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1387,8 +1387,13 @@ namespace ts { return true; } } + + function isEntityNameOrExpression(node: Node): node is EntityName | Expression { + return isEntityName(node) || isExpression(node); + } function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult { + entityName = getOriginalNodeIf(entityName, isEntityNameOrExpression); // get symbol of the first identifier of the entityName let meaning: SymbolFlags; if (entityName.parent.kind === SyntaxKind.TypeQuery) { @@ -2007,6 +2012,7 @@ namespace ts { } function isDeclarationVisible(node: Declaration): boolean { + node = getOriginalNodeIf(node, isDeclaration); function getContainingExternalModule(node: Node) { for (; node; node = node.parent) { if (node.kind === SyntaxKind.ModuleDeclaration) { @@ -2155,6 +2161,7 @@ namespace ts { } function collectLinkedAliases(node: Identifier): Node[] { + node = getOriginalNodeIf(node, isIdentifier); let exportSymbol: Symbol; if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) { exportSymbol = resolveName(node.parent, node.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, Diagnostics.Cannot_find_name_0, node); @@ -4364,11 +4371,11 @@ namespace ts { return getInferredType(context, i); } } - return t; + return t; }; mapper.context = context; - return mapper; + return mapper; } function identityMapper(type: Type): Type { @@ -13815,7 +13822,7 @@ namespace ts { else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) || (entityName.parent.kind === SyntaxKind.JsxSelfClosingElement)) { return getJsxElementTagSymbol(entityName.parent); } - else if (isExpression(entityName)) { + else if (isPartOfExpression(entityName)) { if (nodeIsMissing(entityName)) { // Missing entity name. return undefined; @@ -13953,7 +13960,7 @@ namespace ts { return getTypeFromTypeNode(node); } - if (isExpression(node)) { + if (isPartOfExpression(node)) { return getTypeOfExpression(node); } @@ -14055,6 +14062,7 @@ namespace ts { // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration { + node = getOriginalNodeIf(node, isIdentifier); let symbol = getReferencedValueSymbol(node); if (symbol) { if (symbol.flags & SymbolFlags.ExportValue) { @@ -14084,6 +14092,7 @@ namespace ts { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(node: Identifier): Declaration { + node = getOriginalNodeIf(node, isIdentifier); let symbol = getReferencedValueSymbol(node); return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined; } @@ -14116,6 +14125,7 @@ namespace ts { // When resolved as an expression identifier, if the given node references a nested block scoped entity with // a name that hides an existing name, return the declaration of that entity. Otherwise, return undefined. function getReferencedNestedRedeclaration(node: Identifier): Declaration { + node = getOriginalNodeIf(node, isIdentifier); let symbol = getReferencedValueSymbol(node); return symbol && isNestedRedeclarationSymbol(symbol) ? symbol.valueDeclaration : undefined; } @@ -14123,10 +14133,11 @@ 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(node)); + return isNestedRedeclarationSymbol(getSymbolOfNode(getOriginalNode(node))); } function isValueAliasDeclaration(node: Node): boolean { + node = getOriginalNode(node); switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportClause: @@ -14144,6 +14155,7 @@ namespace ts { } function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean { + node = getOriginalNodeIf(node, isImportEqualsDeclaration); if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; @@ -14171,6 +14183,7 @@ namespace ts { } function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { + node = getOriginalNode(node); if (isAliasSymbolDeclaration(node)) { let symbol = getSymbolOfNode(node); if (getSymbolLinks(symbol).referenced) { @@ -14185,6 +14198,7 @@ namespace ts { } function isImplementationOfOverload(node: FunctionLikeDeclaration) { + node = getOriginalNodeIf(node, isFunctionLike); if (nodeIsPresent(node.body)) { let symbol = getSymbolOfNode(node); let signaturesOfSymbol = getSignaturesOfSymbol(symbol); @@ -14206,6 +14220,7 @@ namespace ts { } function getNodeCheckFlags(node: Node): NodeCheckFlags { + node = getOriginalNode(node); return getNodeLinks(node).flags; } @@ -14213,8 +14228,13 @@ namespace ts { computeEnumMemberValues(node.parent); return getNodeLinks(node).enumMemberValue; } + + function isEnumMemberOrPropertyAccessExpressionOrElementAccessExpression(node: Node): node is EnumMember | PropertyAccessExpression | ElementAccessExpression { + return isEnumMember(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node); + } function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number { + node = getOriginalNodeIf(node, isEnumMemberOrPropertyAccessExpressionOrElementAccessExpression); if (node.kind === SyntaxKind.EnumMember) { return getEnumMemberValue(node); } @@ -14309,12 +14329,14 @@ namespace ts { } function getReferencedValueDeclaration(reference: Identifier): Declaration { + reference = getOriginalNodeIf(reference, isIdentifier); Debug.assert(!nodeIsSynthesized(reference)); let symbol = getReferencedValueSymbol(reference); return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; } function getBlockScopedVariableId(n: Identifier): number { + n = getOriginalNodeIf(n, isIdentifier); Debug.assert(!nodeIsSynthesized(n)); let isVariableDeclarationOrBindingElement = diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ec171d4aee2..12acddb93ee 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -124,6 +124,19 @@ namespace ts { } return result; } + + export function every(array: T[], f: (x: T) => boolean): boolean { + if (array) { + for (let item of array) { + if (!f(item)) { + return false; + } + + return true; + } + } + return false; + } export function map(array: T[], f: (x: T) => U): U[]{ let result: U[]; @@ -181,6 +194,28 @@ namespace ts { } return true; } + + /** + * Returns the first element of an array if non-empty, undefined otherwise. + */ + export function firstOrUndefined(array: T[]): T { + if (array.length === 0) { + return undefined; + } + + return array[0]; + } + + /** + * Returns the only element of an array if non-empty, undefined otherwise. + */ + export function singleOrUndefined(array: T[]): T { + if (array.length === 1) { + return array[0]; + } + + return undefined; + } /** * Returns the last element of an array if non-empty, undefined otherwise. @@ -805,4 +840,4 @@ namespace ts { Debug.assert(false, message); } } -} +} diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index a5763977b7a..335c3df1c44 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -57,7 +57,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { const awaiterHelper = ` var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) { return new Promise(function (resolve, reject) { - generator = generator.call(thisArg, _arguments); + generator = generator.apply(thisArg, _arguments); function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); } function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } } function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } } @@ -866,7 +866,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi increaseIndent(); - if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) { + let parentIsSynthesized = nodeIsSynthesized(parent); + if (!synthesizedNodeStartsOnNewLine(nodes[0]) && (parentIsSynthesized || nodeStartPositionsAreOnSameLine(parent, nodes[0]))) { if (spacesBetweenBraces) { write(" "); } @@ -875,9 +876,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); } + let lastNode: Node; for (let i = 0, n = nodes.length; i < n; i++) { if (i) { - if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) { + if (!synthesizedNodeStartsOnNewLine(nodes[i]) && (parentIsSynthesized || nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i]))) { write(", "); } else { @@ -887,6 +889,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } emit(nodes[i]); + lastNode = nodes[i]; } if (nodes.hasTrailingComma && allowTrailingComma) { @@ -894,8 +897,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } decreaseIndent(); - - if (nodeEndPositionsAreOnSameLine(parent, lastOrUndefined(nodes))) { + + + if (!synthesizedNodeStartsOnNewLine(lastNode) && (parentIsSynthesized || nodeEndPositionsAreOnSameLine(parent, lastNode))) { if (spacesBetweenBraces) { write(" "); } @@ -1120,7 +1124,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return; } - let emitOuterParens = isExpression(parentNode, peekNode, 1) && templateNeedsParens(node); + let emitOuterParens = isPartOfExpression(parentNode, peekNode, 1) + && templateNeedsParens(node); + if (emitOuterParens) { write("("); } @@ -1520,21 +1526,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let name = node.name; Debug.assert(name.kind !== SyntaxKind.BindingElement); - if (name.kind === SyntaxKind.StringLiteral) { + if (isStringLiteral(name)) { pushNode(name); - emitLiteral(name); + emitLiteral(name); popNode(); } - else if (name.kind === SyntaxKind.ComputedPropertyName) { + else if (isComputedPropertyName(name)) { pushNode(name); - emitExpressionForComputedPropertyName(name); + emitExpressionForComputedPropertyName(name); popNode(); } else { write("\""); - if (name.kind === SyntaxKind.NumericLiteral) { - write((name).text); + if (isNumericLiteral(name)) { + write(name.text); } else { writeTextOfNode(currentSourceFile, name); @@ -1559,7 +1565,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // // Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a))); // - if (parentNode && nodeIsDecorated(parentNode)) { + if (nodeIsDecorated(parentNode)) { if (!computedPropertyNamesToGeneratedNames) { computedPropertyNamesToGeneratedNames = []; } @@ -1577,7 +1583,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(" = "); } - emit((name).expression); + emit(name.expression); } function isExpressionIdentifier(node: Node): boolean { @@ -1692,12 +1698,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); if (languageVersion < ScriptTarget.ES6) { - switch (parentNode.kind) { + let originalNode = getOriginalNode(parentNode); + switch (originalNode.kind) { case SyntaxKind.BindingElement: case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parentNode).name === node && resolver.isNestedRedeclaration(parentNode); + return (originalNode).name === node && !nodeIsSynthesized(originalNode) && resolver.isNestedRedeclaration(originalNode); } } return false; @@ -1823,10 +1830,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function needsParenthesisForAwaitExpressionAsYield(node: AwaitExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - if (parentNode.kind === SyntaxKind.BinaryExpression && !isAssignmentOperator((parentNode).operatorToken.kind)) { + if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { return true; } - else if (parentNode.kind === SyntaxKind.ConditionalExpression && (parentNode).condition === node) { + else if (isConditionalExpression(parentNode) && parentNode.condition === node) { return true; } @@ -2500,8 +2507,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitParenExpression(node: ParenthesizedExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - let parent = parentNode; - // 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. @@ -2529,8 +2534,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi operand.kind !== SyntaxKind.DeleteExpression && operand.kind !== SyntaxKind.PostfixUnaryExpression && operand.kind !== SyntaxKind.NewExpression && - !(operand.kind === SyntaxKind.CallExpression && parent.kind === SyntaxKind.NewExpression) && - !(operand.kind === SyntaxKind.FunctionExpression && parent.kind === SyntaxKind.CallExpression)) { + !(operand.kind === SyntaxKind.CallExpression && parentNode.kind === SyntaxKind.NewExpression) && + !(operand.kind === SyntaxKind.FunctionExpression && parentNode.kind === SyntaxKind.CallExpression)) { emit(operand); return; } @@ -2573,15 +2578,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return false; } - debugger; - - const parentNode = currentNode; const isVariableDeclarationOrBindingElement = - parentNode && (parentNode.kind === SyntaxKind.VariableDeclaration || parentNode.kind === SyntaxKind.BindingElement); + currentNode && (currentNode.kind === SyntaxKind.VariableDeclaration || currentNode.kind === SyntaxKind.BindingElement); const targetDeclaration = isVariableDeclarationOrBindingElement - ? parentNode + ? currentNode : resolver.getReferencedValueDeclaration(node); return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true); @@ -2777,6 +2779,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } + function isBlockWithSynthesizedStatementsOnNewLine(node: Node) { + if (isBlock(node) && forEach(node.statements, synthesizedNodeStartsOnNewLine)) { + return true; + } + return false; + } + + function isSingleLineSynthesizedBlock(node: Node) { + verifyStackBehavior(StackBehavior.Unspecified, node); + + if (isBlock(node) && nodeIsSynthesized(node) && node.statements.length === 1 && nodeIsSynthesized(node.statements[0])) { + return !(node.statements[0]).startsOnNewLine; + } + } + function emitBlock(node: Block) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); @@ -2787,6 +2804,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return; } + if (isSingleLineSynthesizedBlock(node)) { + emitToken(SyntaxKind.OpenBraceToken, node.pos); + write(" "); + emit(node.statements[0]); + write(" "); + emitToken(SyntaxKind.CloseBraceToken, node.statements.end); + return; + } + emitToken(SyntaxKind.OpenBraceToken, node.pos); increaseIndent(); scopeEmitStart(parentNode); @@ -3290,8 +3316,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emit(node.statement); } + function getContainingModule(node: Node): ModuleDeclaration { + do { + node = getOriginalNode(node); + node = node.parent; + } while (node && node.kind !== SyntaxKind.ModuleDeclaration); + return node; + } + + function isModuleDeclarationOrGeneratedNamespace(node: Node): node is ModuleDeclaration | ExpressionStatement { + return isModuleDeclaration(node) || (isExpressionStatement(node) && !!(node.flags & NodeFlags.GeneratedNamespace)); + } + function emitContainingModuleName() { - let container = findAncestorNode(isModuleDeclaration); + let container = getOriginalNode(findAncestorNode(isModuleDeclarationOrGeneratedNamespace)); write(container ? getGeneratedNameForNode(container) : "exports"); } @@ -3300,7 +3338,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitStart(node.name); if (getCombinedNodeFlags() & NodeFlags.Export) { - let container = findAncestorNode(isModuleDeclaration); + let container = getOriginalNode(findAncestorNode(isModuleDeclarationOrGeneratedNamespace)); if (container) { write(getGeneratedNameForNode(container)); write("."); @@ -4005,6 +4043,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCaptureThisForNodeIfNecessary(node: Node): void { verifyStackBehavior(StackBehavior.Unspecified); + if (compilerOptions.experimentalTransforms) { + return; + } + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureThis) { writeLine(); emitStart(node); @@ -4320,7 +4362,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi pushNode(body); let preambleEmitted = writer.getTextPos() !== initialTextPos; - if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) { + if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body) + && !isBlockWithSynthesizedStatementsOnNewLine(body) + && (!nodeIsSynthesized(body) || isSingleLineSynthesizedBlock(body))) { for (let statement of body.statements) { write(" "); emit(statement); @@ -4960,6 +5004,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } function emitClassLikeDeclarationBelowES6(node: ClassLikeDeclaration) { + Debug.assert(!compilerOptions.experimentalTransforms, "This function should not be called when using '--experimentalTransforms'."); verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); if (node.kind === SyntaxKind.ClassDeclaration) { @@ -5632,6 +5677,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } function emitEnumDeclaration(node: EnumDeclaration) { + Debug.assert(!compilerOptions.experimentalTransforms, "This function should not be called when using '--experimentalTransforms'."); verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); // const enums are completely erased during compilation. @@ -5753,6 +5799,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } function emitModuleDeclaration(node: ModuleDeclaration) { + Debug.assert(!compilerOptions.experimentalTransforms, "This function should not be called when using '--experimentalTransforms'."); + verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); // Emit only if this module is non-ambient. @@ -7222,7 +7270,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // Process tree transformations let statements = node.statements; - if (compilerOptions.experimentalTransforms) { + if (compilerOptions.experimentalTransforms || true) { let context = new transform.VisitorContext(compilerOptions, currentSourceFile, resolver, generatedNameSet, nodeToGeneratedName); statements = transformationChain(context, node.statements); } @@ -7290,25 +7338,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi popNode(); } - function emitWithStackBehavior(node: T, emit: (node: T) => U, stackBehavior: StackBehavior): U { - let result: U; - if (stackBehavior === StackBehavior.NodeIsOnTopOfStack && currentNode !== node) { - pushNode(node); - result = emit(node); - popNode(); - } - else if (stackBehavior === StackBehavior.ParentIsOnTopOfStack && currentNode === node) { - popNode(); - result = emit(node); - pushNode(node); - } - else { - result = emit(node); - } - - return result; - } - function emitNodeWithoutSourceMap(node: Node): void { if (!node) { return; @@ -7601,11 +7630,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getLeadingCommentsToEmit(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - if ((node).leadingCommentRanges) { + if (nodeIsSynthesized(node)) { return (node).leadingCommentRanges; } - node = getOriginalNode(node); + //node = getOriginalNode(node); // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments if (parentNode) { @@ -7625,11 +7654,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getTrailingCommentsToEmit(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - if ((node).trailingCommentRanges) { + if (nodeIsSynthesized(node)) { return (node).trailingCommentRanges; } - node = getOriginalNode(node); + //node = getOriginalNode(node); + // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments if (parentNode && !nodeIsSynthesized(parentNode)) { if (parentNode.kind === SyntaxKind.SourceFile || node.end !== parentNode.end) { diff --git a/src/compiler/factory.generated.ts b/src/compiler/factory.generated.ts index fe000b18f17..31e5ef10855 100644 --- a/src/compiler/factory.generated.ts +++ b/src/compiler/factory.generated.ts @@ -46,8 +46,17 @@ namespace ts { } return node; } - export function createThisKeyword(location?: TextRange, flags?: NodeFlags): LeftHandSideExpression { - return createNode(SyntaxKind.ThisKeyword, location, flags); + export function createFalseKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + return createNode(SyntaxKind.FalseKeyword, location, flags); + } + export function createSuperKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + return createNode(SyntaxKind.SuperKeyword, location, flags); + } + export function createThisKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + return createNode(SyntaxKind.ThisKeyword, location, flags); + } + export function createTrueKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + return createNode(SyntaxKind.TrueKeyword, location, flags); } export function createQualifiedName(left?: EntityName, right?: Identifier, location?: TextRange, flags?: NodeFlags): QualifiedName { let node = createNode(SyntaxKind.QualifiedName, location, flags); @@ -110,10 +119,10 @@ namespace ts { return node; } export function updateParameter(node: ParameterDeclaration, decorators: Array, modifiers: Array - , name: BindingPattern | Identifier, type: TypeNode, initializer: Expression): ParameterDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type || - initializer !== node.initializer) { - let newNode = createParameter(decorators, modifiers, node.dotDotDotToken, name, node.questionToken, type, initializer); + , 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); return updateFrom(node, newNode); } return node; @@ -994,15 +1003,20 @@ namespace ts { } return node; } - export function createVariableStatement(declarationList?: VariableDeclarationList, + export function createVariableStatement(decorators?: Array, modifiers?: Array, declarationList?: VariableDeclarationList, location?: TextRange, flags?: NodeFlags): VariableStatement { let node = createNode(SyntaxKind.VariableStatement, location, flags); - node.declarationList = declarationList; + if (arguments.length) { + node.decorators = decorators && createNodeArray(decorators) + setModifiers(node, modifiers); + node.declarationList = declarationList; + } return node; } - export function updateVariableStatement(node: VariableStatement, declarationList: VariableDeclarationList): VariableStatement { - if (declarationList !== node.declarationList) { - let newNode = createVariableStatement(declarationList); + export function updateVariableStatement(node: VariableStatement, decorators: Array, modifiers: Array + , declarationList: VariableDeclarationList): VariableStatement { + if (decorators !== node.decorators || modifiers !== node.modifiers || declarationList !== node.declarationList) { + let newNode = createVariableStatement(decorators, modifiers, declarationList); return updateFrom(node, newNode); } return node; @@ -1242,23 +1256,20 @@ namespace ts { export function createDebuggerStatement(location?: TextRange, flags?: NodeFlags): DebuggerStatement { return createNode(SyntaxKind.DebuggerStatement, location, flags); } - export function createVariableDeclaration(decorators?: Array, modifiers?: Array, name?: BindingPattern | Identifier, - type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): VariableDeclaration { + export function createVariableDeclaration(name?: BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, + location?: TextRange, flags?: NodeFlags): VariableDeclaration { let node = createNode(SyntaxKind.VariableDeclaration, location, flags); if (arguments.length) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); node.name = name; node.type = type; node.initializer = initializer; } return node; } - export function updateVariableDeclaration(node: VariableDeclaration, decorators: Array, modifiers: Array - , name: BindingPattern | Identifier, type: TypeNode, initializer: Expression): VariableDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type || - initializer !== node.initializer) { - let newNode = createVariableDeclaration(decorators, modifiers, name, type, initializer); + export function updateVariableDeclaration(node: VariableDeclaration, name: BindingPattern | Identifier, type: TypeNode + , initializer: Expression): VariableDeclaration { + if (name !== node.name || type !== node.type || initializer !== node.initializer) { + let newNode = createVariableDeclaration(name, type, initializer); return updateFrom(node, newNode); } return node; @@ -1759,14 +1770,18 @@ namespace ts { } return node; } - export function createHeritageClause(types?: Array, location?: TextRange, flags?: NodeFlags): HeritageClause { + export function createHeritageClause(token?: SyntaxKind, types?: Array, + location?: TextRange, flags?: NodeFlags): HeritageClause { let node = createNode(SyntaxKind.HeritageClause, location, flags); - node.types = types && createNodeArray(types) + if (arguments.length) { + node.token = token; + node.types = types && createNodeArray(types) + } return node; } export function updateHeritageClause(node: HeritageClause, types: Array): HeritageClause { if (types !== node.types) { - let newNode = createHeritageClause(types); + let newNode = createHeritageClause(node.token, types); return updateFrom(node, newNode); } return node; @@ -1787,35 +1802,30 @@ namespace ts { } return node; } - export function createPropertyAssignment(name?: PropertyName, questionToken?: Node, initializer?: Expression, + export function createPropertyAssignment(name?: PropertyName, initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyAssignment { let node = createNode(SyntaxKind.PropertyAssignment, location, flags); if (arguments.length) { node.name = name; - node.questionToken = questionToken; node.initializer = initializer; } return node; } export function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment { if (name !== node.name || initializer !== node.initializer) { - let newNode = createPropertyAssignment(name, node.questionToken, initializer); + let newNode = createPropertyAssignment(name, initializer); return updateFrom(node, newNode); } return node; } - export function createShorthandPropertyAssignment(name?: Identifier, questionToken?: Node, - location?: TextRange, flags?: NodeFlags): ShorthandPropertyAssignment { + export function createShorthandPropertyAssignment(name?: Identifier, location?: TextRange, flags?: NodeFlags): ShorthandPropertyAssignment { let node = createNode(SyntaxKind.ShorthandPropertyAssignment, location, flags); - if (arguments.length) { - node.name = name; - node.questionToken = questionToken; - } + node.name = name; return node; } export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier): ShorthandPropertyAssignment { if (name !== node.name) { - let newNode = createShorthandPropertyAssignment(name, node.questionToken); + let newNode = createShorthandPropertyAssignment(name); return updateFrom(node, newNode); } return node; @@ -2144,8 +2154,14 @@ namespace ts { return factory.createTemplateTail((node).text, location, flags); case SyntaxKind.Identifier: return factory.createIdentifier((node).text, (node).originalKeywordKind, location, flags); + case SyntaxKind.FalseKeyword: + return factory.createFalseKeyword(location, flags); + case SyntaxKind.SuperKeyword: + return factory.createSuperKeyword(location, flags); case SyntaxKind.ThisKeyword: return factory.createThisKeyword(location, flags); + case SyntaxKind.TrueKeyword: + return factory.createTrueKeyword(location, flags); case SyntaxKind.QualifiedName: return factory.createQualifiedName((node).left, (node).right, location, flags); case SyntaxKind.ComputedPropertyName: @@ -2307,7 +2323,8 @@ namespace ts { case SyntaxKind.Block: return factory.createBlock((node).statements, location, flags); case SyntaxKind.VariableStatement: - return factory.createVariableStatement((node).declarationList, location, flags); + return factory.createVariableStatement((node).decorators, (node).modifiers, + (node).declarationList, location, flags); case SyntaxKind.EmptyStatement: return factory.createEmptyStatement(location, flags); case SyntaxKind.ExpressionStatement: @@ -2348,9 +2365,8 @@ namespace ts { case SyntaxKind.DebuggerStatement: return factory.createDebuggerStatement(location, flags); case SyntaxKind.VariableDeclaration: - return factory.createVariableDeclaration((node).decorators, (node).modifiers, - (node).name, (node).type, (node).initializer, - location, flags); + return factory.createVariableDeclaration((node).name, (node).type, + (node).initializer, location, flags); case SyntaxKind.VariableDeclarationList: return factory.createVariableDeclarationList((node).declarations, location, flags); case SyntaxKind.FunctionDeclaration: @@ -2432,15 +2448,14 @@ namespace ts { case SyntaxKind.DefaultClause: return factory.createDefaultClause((node).statements, location, flags); case SyntaxKind.HeritageClause: - return factory.createHeritageClause((node).types, location, flags); + return factory.createHeritageClause((node).token, (node).types, location, flags); case SyntaxKind.CatchClause: return factory.createCatchClause((node).variableDeclaration, (node).block, location, flags); case SyntaxKind.PropertyAssignment: - return factory.createPropertyAssignment((node).name, (node).questionToken, - (node).initializer, location, flags); + return factory.createPropertyAssignment((node).name, (node).initializer, + location, flags); case SyntaxKind.ShorthandPropertyAssignment: - return factory.createShorthandPropertyAssignment((node).name, - (node).questionToken, location, flags); + return factory.createShorthandPropertyAssignment((node).name, location, flags); case SyntaxKind.EnumMember: return factory.createEnumMember((node).name, (node).initializer, location, flags); case SyntaxKind.JSDocTypeExpression: @@ -2520,19 +2535,19 @@ namespace ts { export function isIdentifier(node: Node): node is Identifier { return node && node.kind === SyntaxKind.Identifier; } - export function isFalseKeyword(node: Node): node is LeftHandSideExpression { + export function isFalseKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.FalseKeyword; } - export function isNullKeyword(node: Node): node is LeftHandSideExpression { + export function isNullKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.NullKeyword; } - export function isSuperKeyword(node: Node): node is LeftHandSideExpression { + export function isSuperKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.SuperKeyword; } - export function isThisKeyword(node: Node): node is LeftHandSideExpression { + export function isThisKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.ThisKeyword; } - export function isTrueKeyword(node: Node): node is LeftHandSideExpression { + export function isTrueKeyword(node: Node): node is PrimaryExpression { return node && node.kind === SyntaxKind.TrueKeyword; } export function isQualifiedName(node: Node): node is QualifiedName { @@ -2950,6 +2965,56 @@ namespace ts { } return false; } + export function isExpression(node: Node): node is Expression { + if (node) { + switch (node.kind) { + case SyntaxKind.OmittedExpression: + case SyntaxKind.Identifier: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.ClassExpression: + return true; + } + } + return false; + } export function isBindingPatternOrIdentifier(node: Node): node is BindingPattern | Identifier { if (node) { switch (node.kind) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index c89e3f80c7c..b2605b11dd5 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -42,8 +42,13 @@ namespace ts { } export function attachCommentRanges(node: T, leadingCommentRanges: CommentRange[], trailingCommentRanges?: CommentRange[]): T { - (node).leadingCommentRanges = leadingCommentRanges; - (node).trailingCommentRanges = trailingCommentRanges; + (node).leadingCommentRanges = leadingCommentRanges; + (node).trailingCommentRanges = trailingCommentRanges; + return node; + } + + export function startOnNewLine(node: T): T { + (node).startsOnNewLine = true; return node; } @@ -73,6 +78,10 @@ namespace ts { } } + export function cloneNodeArray(array: NodeArray): NodeArray { + return array ? factory.createNodeArray(array.slice(0), /*location*/ array) : undefined; + } + export function createNode(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags): T { return setNodeFlags(setTextRange(new (getNodeConstructor(kind))(), location), flags); } @@ -120,6 +129,35 @@ namespace ts { flags ); } + + export const enum BinaryOperand { + Left, + Right + } + + export function parenthesizeForBinary(expr: Expression, operator: SyntaxKind) { + // When diagnosing whether the expression needs parentheses, the decision should be based + // on the innermost expression in a chain of nested type assertions. + while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) { + expr = (expr).expression; + } + + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (isParenthesizedExpression(expr)) { + return expr; + } + + let exprPrecedence = getExpressionPrecedence(expr); + let operatorPrecedence = getBinaryOperatorPrecedence(operator); + if (exprPrecedence < operatorPrecedence) { + // lower precedence, the expression needs parenthesis + return factory.createParenthesizedExpression(expr); + } + else { + // higher precedence. + return expr; + } + } export function parenthesizeForAccess(expr: Expression): LeftHandSideExpression { // When diagnosing whether the expression needs parentheses, the decision should be based @@ -146,9 +184,9 @@ namespace ts { return factory.createParenthesizedExpression(expr); } - export function createCallExpression2(expression: LeftHandSideExpression, _arguments?: Expression[], location?: TextRange, flags?: NodeFlags) { + export function createCallExpression2(expression: Expression, _arguments?: Expression[], location?: TextRange, flags?: NodeFlags) { return factory.createCallExpression( - expression, + parenthesizeForAccess(expression), /*typeArguments*/ undefined, _arguments, location, @@ -156,21 +194,43 @@ namespace ts { ); } - export function createAssignmentExpression(left: Expression, right: Expression, location?: TextRange, flags?: NodeFlags) { - return factory.createBinaryExpression2(left, SyntaxKind.EqualsToken, right, location, flags); + export function createObjectLiteralExpression2(properties?: ObjectLiteralElement[]) { + return createObjectLiteralExpression( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createNodeArray(properties) + ); } - export function createAssignmentExpressionStatement(left: Expression, right: Expression, location?: TextRange, flags?: NodeFlags) { - return factory.createExpressionStatement(factory.createAssignmentExpression(left, right), location, flags); + export function createAssignmentExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.EqualsToken, right); + } + + export function createStrictEqualityExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.EqualsEqualsEqualsToken, right); + } + + export function createStrictInequalityExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.ExclamationEqualsEqualsToken, right); + } + + export function createLogicalAndExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.AmpersandAmpersandToken, right); + } + + export function createLogicalOrExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.BarBarToken, right); + } + + export function createCommaExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.CommaToken, right); } - export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange, flags?: NodeFlags) { + export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression) { return factory.createBinaryExpression( - left, + parenthesizeForBinary(left, operator), factory.createNode(operator), - right, - location, - flags + parenthesizeForBinary(right, operator) ); } @@ -186,21 +246,7 @@ namespace ts { ); } - export function createInlineFunctionExpressionEvaluation(parameters: ParameterDeclaration[], bodyStatements: Statement[], _arguments: Expression[], location?: TextRange, flags?: NodeFlags) { - return factory.createCallExpression2( - factory.createParenthesizedExpression( - factory.createFunctionExpression5( - parameters, - bodyStatements - ) - ), - _arguments, - location, - flags - ); - } - - export function createParameter2(name: BindingPattern | Identifier, location?: TextRange, flags?: NodeFlags) { + export function createParameter2(name: BindingPattern | Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { return factory.createParameter( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -208,7 +254,7 @@ namespace ts { name, /*questionToken*/ undefined, /*type*/ undefined, - /*initializer*/ undefined, + initializer, location, flags ); @@ -228,20 +274,18 @@ namespace ts { ); } - export function createVariableStatement2(name: Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { + export function createVariableStatement2(declarationList: VariableDeclarationList, location?: TextRange, flags?: NodeFlags) { return factory.createVariableStatement( - factory.createVariableDeclarationList([ - factory.createVariableDeclaration2(name, initializer) - ], /*location*/ undefined, flags & (NodeFlags.Let | NodeFlags.Const)), + /*decorators*/ undefined, + /*modifiers*/ undefined, + declarationList, location, - flags & ~(NodeFlags.Let | NodeFlags.Const) + flags ); } - export function createVariableDeclaration2(name: Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { + export function createVariableDeclaration2(name: Identifier | BindingPattern, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { return factory.createVariableDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, name, /*type*/ undefined, initializer, @@ -250,14 +294,16 @@ namespace ts { ); } - export function createClassDeclaration2(modifiers: Modifier[], name: Identifier, heritageClause: HeritageClause, members: ClassElement[]): ClassDeclaration { + export function createClassDeclaration2(name: Identifier, heritageClause: HeritageClause, members: ClassElement[], location?: TextRange, flags?: NodeFlags): ClassDeclaration { return factory.createClassDeclaration( /*decorators*/ undefined, - modifiers, + /*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClause ? [heritageClause] : undefined, - members + members, + location, + flags ); } @@ -272,11 +318,56 @@ namespace ts { ); } - export function createClassExpression3(heritageClause: HeritageClause, members: ClassElement[]) { - return factory.createClassExpression2( - /*name*/ undefined, - heritageClause, - members + export function createConstructor2(parameters: Array, body: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration { + return factory.createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + /*type*/ undefined, + body, + location, + flags + ); + } + + export function createMethodDeclaration2(name: PropertyName, parameters: Array, body: Block, location?: TextRange, flags?: NodeFlags): MethodDeclaration { + return factory.createMethodDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + name, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + body, + location, + flags + ); + } + + export function createGetAccessor2(name: PropertyName, parameters: Array, body: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration { + return factory.createGetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + name, + parameters, + /*type*/ undefined, + body, + location, + flags + ); + } + + export function createSetAccessor2(name: PropertyName, parameters: Array, body: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration { + return factory.createSetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + name, + parameters, + /*type*/ undefined, + body, + location, + flags ); } @@ -294,22 +385,28 @@ namespace ts { flags ); } - - export function createFunctionDeclaration3(name: Identifier, parameters: ParameterDeclaration[], body: Statement[], location?: TextRange, flags?: NodeFlags) { - return factory.createFunctionDeclaration2( + + export function createFunctionDeclaration3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { + return factory.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + asteriskToken, name, + /*typeParameters*/ undefined, parameters, - factory.createBlock(body || []), + /*type*/ undefined, + body, location, - flags); - } + flags + ); + } export function createFunctionExpression2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { return factory.createFunctionExpression( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, - /*name*/ undefined, + name, /*typeParameters*/ undefined, parameters, /*type*/ undefined, @@ -319,31 +416,31 @@ namespace ts { ); } - export function createFunctionExpression3(parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { - return factory.createFunctionExpression2( - /*name*/ undefined, + export function createFunctionExpression3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { + return factory.createFunctionExpression( + /*decorators*/ undefined, + /*modifiers*/ undefined, + asteriskToken, + name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body, location, flags ); } - - export function createFunctionExpression4(name: Identifier, parameters: ParameterDeclaration[], body: Statement[], location?: TextRange, flags?: NodeFlags) { - return factory.createFunctionExpression2( + + export function createGeneratorFunctionExpression(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { + return factory.createFunctionExpression( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createNode(SyntaxKind.AsteriskToken), name, + /*typeParameters*/ undefined, parameters, - factory.createBlock(body || []), - location, - flags - ); - } - - export function createFunctionExpression5(parameters: ParameterDeclaration[], body: Statement[], location?: TextRange, flags?: NodeFlags) { - return factory.createFunctionExpression2( - /*name*/ undefined, - parameters, - factory.createBlock(body || []), + /*type*/ undefined, + body, location, flags ); @@ -398,15 +495,96 @@ namespace ts { ); } + export function createApplyCall(target: Expression, thisArg: Expression, _arguments: Expression, location?: TextRange, flags?: NodeFlags) { + let applyName = createIdentifier("apply"); + let propExpr = createPropertyAccessExpression2(target, applyName); + return factory.createCallExpression2(propExpr, [thisArg, _arguments], location, flags); + } + + export function createExtendsHelperCall(name: Identifier) { + let extendsName = factory.createIdentifier("__extends"); + let superName = factory.createIdentifier("_super"); + let callExpr = factory.createCallExpression2(extendsName, [name, superName]); + return callExpr; + } + + export function createAwaiterHelperCall(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) { + let thisExpr = factory.createThisKeyword(); + let awaiterName = factory.createIdentifier("__awaiter"); + let argumentsExpr = hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZeroExpression(); + let promiseExpr = promiseConstructor ? convertEntityNameToExpression(promiseConstructor) : factory.createIdentifier("Promise"); + let generatorFunc = factory.createGeneratorFunctionExpression(/*name*/ undefined, [], body); + let callExpr = factory.createCallExpression2(awaiterName, [thisExpr, argumentsExpr, promiseExpr, generatorFunc]); + return callExpr; + } + + function convertEntityNameToExpression(node: EntityName | Expression): Expression { + if (isQualifiedName(node)) { + let left = convertEntityNameToExpression(node.left); + let right = factory.cloneNode(node.right); + return factory.createPropertyAccessExpression2(left, right); + } + else { + return factory.cloneNode(node); + } + } + + export function createDecorateHelperCall(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) { + let _arguments: Expression[] = [ + factory.createArrayLiteralExpression(decoratorExpressions), + target + ]; + if (memberName) { + _arguments.push(memberName); + if (descriptor) { + _arguments.push(descriptor); + } + } + let decorateHelperName = factory.createIdentifier("__decorate"); + let decoratorsExpr = factory.createArrayLiteralExpression(decoratorExpressions); + let callExpr = factory.createCallExpression2(decorateHelperName, _arguments); + return callExpr; + } + + export function createParamHelperCall(parameterIndex: number, decoratorExpression: Expression) { + let paramHelperName = factory.createIdentifier("__param"); + let parameterIndexExpr = factory.createNumericLiteral(String(parameterIndex)); + let callExpr = factory.createCallExpression2(paramHelperName, [parameterIndexExpr, decoratorExpression]); + return callExpr; + } + + export function createMetadataHelperCall(metadataKey: string, metadataValue: Expression) { + let metadataHelperName = factory.createIdentifier("__metadata"); + let metadataKeyExpr = factory.createStringLiteral(metadataKey); + let callExpr = factory.createCallExpression2(metadataHelperName, [metadataKeyExpr, metadataValue]); + return callExpr; + } + + export function createDefinePropertyCall(target: Expression, memberName: Expression, descriptor: Expression) { + let globalObjectName = factory.createIdentifier("Object"); + let definePropertyName = factory.createIdentifier("defineProperty"); + let propExpr = factory.createPropertyAccessExpression(globalObjectName, factory.createNode(SyntaxKind.DotToken), definePropertyName); + let callExpr = factory.createCallExpression2(propExpr, [target, memberName, descriptor]); + return callExpr; + } + + export function createGetOwnPropertyDescriptorCall(target: Expression, memberName: Expression) { + let globalObjectName = factory.createIdentifier("Object"); + let getOwnPropertyDescriptorName = factory.createIdentifier("getOwnPropertyDescriptor"); + let propExpr = factory.createPropertyAccessExpression(globalObjectName, factory.createNode(SyntaxKind.DotToken), getOwnPropertyDescriptorName); + let callExpr = factory.createCallExpression2(propExpr, [target, memberName]); + return callExpr; + } + export function createDefaultValueCheck(value: Expression, defaultValue: Expression, ensureIdentifier: (value: Expression) => 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); // === void 0 ? : - return factory.createConditionalExpression2(factory.createAssignmentExpression(value, factory.createVoidZeroExpression()), defaultValue, value, location, flags); + return factory.createConditionalExpression2(factory.createStrictEqualityExpression(value, factory.createVoidZeroExpression()), defaultValue, value, location, flags); } - + export function createMemberAccessForPropertyName(target: Expression, memberName: DeclarationName, location?: TextRange, flags?: NodeFlags): MemberExpression { if (isStringLiteral(memberName) || isNumericLiteral(memberName)) { return factory.createElementAccessExpression2( @@ -438,7 +616,7 @@ namespace ts { export function inlineExpressions(expressions: Expression[]) { let expression = expressions[0]; for (let i = 1; i < expressions.length; i++) { - expression = factory.createBinaryExpression2( + expression = createBinaryExpression2( expression, SyntaxKind.CommaToken, expressions[i] diff --git a/src/compiler/transform.generated.ts b/src/compiler/transform.generated.ts index 2fa1c993f2e..cd60ee62aef 100644 --- a/src/compiler/transform.generated.ts +++ b/src/compiler/transform.generated.ts @@ -3,989 +3,694 @@ /// /* @internal */ namespace ts.transform { - export function accept(context: VisitorContext, node: Node, visitor: Visitor): Node { - if (!node || !visitor) { - return node; + export function accept(context: VisitorContext, node: Node, visitor: Visitor, write: (node: Node) => void): void { + if (!node) { + return; } switch (node.kind) { case SyntaxKind.QualifiedName: - return factory.updateQualifiedName( + return write(factory.updateQualifiedName( node, - visitEntityName(context, (node).left, visitor), - visitIdentifier(context, (node).right, visitor)); + visitNode(context, (node).left, visitor), + visitNode(context, (node).right, visitor))); case SyntaxKind.ComputedPropertyName: - return factory.updateComputedPropertyName( + return write(factory.updateComputedPropertyName( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.TypeParameter: - return factory.updateTypeParameter( + return write(factory.updateTypeParameter( node, - visitIdentifier(context, (node).name, visitor), - visitTypeNode(context, (node).constraint, visitor), - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).constraint, visitor), + visitNode(context, (node).expression, visitor))); case SyntaxKind.Parameter: - return factory.updateParameter( + return write(factory.updateParameter( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitBindingPatternOrIdentifier(context, (node).name, visitor), - visitTypeNode(context, (node).type, visitor), - visitExpression(context, (node).initializer, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + (node).questionToken, + visitNode(context, (node).type, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.Decorator: - return factory.updateDecorator( + return write(factory.updateDecorator( node, - visitLeftHandSideExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.PropertySignature: - return factory.updatePropertySignature( + return write(factory.updatePropertySignature( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.PropertyDeclaration: - return factory.updatePropertyDeclaration( + return write(factory.updatePropertyDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitTypeNode(context, (node).type, visitor), - visitExpression(context, (node).initializer, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + visitNode(context, (node).type, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.MethodSignature: - return factory.updateMethodSignature( + return write(factory.updateMethodSignature( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.MethodDeclaration: - return factory.updateMethodDeclaration( + return write(factory.updateMethodDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlock(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitNode(context, (node).body, visitor))); case SyntaxKind.Constructor: - return factory.updateConstructor( + return write(factory.updateConstructor( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlock(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitNode(context, (node).body, visitor))); case SyntaxKind.GetAccessor: - return factory.updateGetAccessor( + return write(factory.updateGetAccessor( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlockInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitBlockInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.SetAccessor: - return factory.updateSetAccessor( + return write(factory.updateSetAccessor( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitPropertyName(context, (node).name, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlockInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitBlockInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.CallSignature: - return factory.updateCallSignature( + return write(factory.updateCallSignature( node, - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.ConstructSignature: - return factory.updateConstructSignature( + return write(factory.updateConstructSignature( node, - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.IndexSignature: - return factory.updateIndexSignature( + return write(factory.updateIndexSignature( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.TypePredicate: - return factory.updateTypePredicate( + return write(factory.updateTypePredicate( node, - visitIdentifier(context, (node).parameterName, visitor), - visitTypeNode(context, (node).type, visitor)); + visitNode(context, (node).parameterName, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.TypeReference: - return factory.updateTypeReference( + return write(factory.updateTypeReference( node, - visitEntityName(context, (node).typeName, visitor), - visitNodeArrayOfTypeNode(context, (node).typeArguments, visitor)); + visitNode(context, (node).typeName, visitor), + >visitNodes(context, (node).typeArguments, visitor))); case SyntaxKind.FunctionType: - return factory.updateFunctionType( + return write(factory.updateFunctionType( node, - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.ConstructorType: - return factory.updateConstructorType( + return write(factory.updateConstructorType( node, - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.TypeQuery: - return factory.updateTypeQuery( + return write(factory.updateTypeQuery( node, - visitEntityName(context, (node).exprName, visitor)); + visitNode(context, (node).exprName, visitor))); case SyntaxKind.TypeLiteral: - return factory.updateTypeLiteral( + return write(factory.updateTypeLiteral( node, - visitNodeArrayOfTypeElement(context, (node).members, visitor)); + >visitNodes(context, (node).members, visitor))); case SyntaxKind.ArrayType: - return factory.updateArrayType( + return write(factory.updateArrayType( node, - visitTypeNode(context, (node).elementType, visitor)); + visitNode(context, (node).elementType, visitor))); case SyntaxKind.TupleType: - return factory.updateTupleType( + return write(factory.updateTupleType( node, - visitNodeArrayOfTypeNode(context, (node).elementTypes, visitor)); + >visitNodes(context, (node).elementTypes, visitor))); case SyntaxKind.UnionType: - return factory.updateUnionType( + return write(factory.updateUnionType( node, - visitNodeArrayOfTypeNode(context, (node).types, visitor)); + >visitNodes(context, (node).types, visitor))); case SyntaxKind.IntersectionType: - return factory.updateIntersectionType( + return write(factory.updateIntersectionType( node, - visitNodeArrayOfTypeNode(context, (node).types, visitor)); + >visitNodes(context, (node).types, visitor))); case SyntaxKind.ParenthesizedType: - return factory.updateParenthesizedType( + return write(factory.updateParenthesizedType( node, - visitTypeNode(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.ObjectBindingPattern: - return factory.updateObjectBindingPattern( + return write(factory.updateObjectBindingPattern( node, - visitNodeArrayOfBindingElement(context, (node).elements, visitor)); + >visitNodes(context, (node).elements, visitor))); case SyntaxKind.ArrayBindingPattern: - return factory.updateArrayBindingPattern( + return write(factory.updateArrayBindingPattern( node, - visitNodeArrayOfBindingElement(context, (node).elements, visitor)); + >visitNodes(context, (node).elements, visitor))); case SyntaxKind.BindingElement: - return factory.updateBindingElement( + return write(factory.updateBindingElement( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).propertyName, visitor), - visitBindingPatternOrIdentifier(context, (node).name, visitor), - visitExpression(context, (node).initializer, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).propertyName, visitor), + visitNode(context, (node).name, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.ArrayLiteralExpression: - return factory.updateArrayLiteralExpression( + return write(factory.updateArrayLiteralExpression( node, - visitNodeArrayOfExpression(context, (node).elements, visitor)); + >visitNodes(context, (node).elements, visitor))); case SyntaxKind.ObjectLiteralExpression: - return factory.updateObjectLiteralExpression( + return write(factory.updateObjectLiteralExpression( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitNodeArrayOfObjectLiteralElement(context, (node).properties, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + >visitNodes(context, (node).properties, visitor))); case SyntaxKind.PropertyAccessExpression: - return factory.updatePropertyAccessExpression( + return write(factory.updatePropertyAccessExpression( node, - visitLeftHandSideExpression(context, (node).expression, visitor), - visitIdentifier(context, (node).name, visitor)); + visitNode(context, (node).expression, visitor), + visitNode(context, (node).name, visitor))); case SyntaxKind.ElementAccessExpression: - return factory.updateElementAccessExpression( + return write(factory.updateElementAccessExpression( node, - visitLeftHandSideExpression(context, (node).expression, visitor), - visitExpression(context, (node).argumentExpression, visitor)); + visitNode(context, (node).expression, visitor), + visitNode(context, (node).argumentExpression, visitor))); case SyntaxKind.CallExpression: - return factory.updateCallExpression( + return write(factory.updateCallExpression( node, - visitLeftHandSideExpression(context, (node).expression, visitor), - visitNodeArrayOfTypeNode(context, (node).typeArguments, visitor), - visitNodeArrayOfExpression(context, (node).arguments, visitor)); + visitNode(context, (node).expression, visitor), + >visitNodes(context, (node).typeArguments, visitor), + >visitNodes(context, (node).arguments, visitor))); case SyntaxKind.NewExpression: - return factory.updateNewExpression( + return write(factory.updateNewExpression( node, - visitLeftHandSideExpression(context, (node).expression, visitor), - visitNodeArrayOfTypeNode(context, (node).typeArguments, visitor), - visitNodeArrayOfExpression(context, (node).arguments, visitor)); + visitNode(context, (node).expression, visitor), + >visitNodes(context, (node).typeArguments, visitor), + >visitNodes(context, (node).arguments, visitor))); case SyntaxKind.TaggedTemplateExpression: - return factory.updateTaggedTemplateExpression( + return write(factory.updateTaggedTemplateExpression( node, - visitLeftHandSideExpression(context, (node).tag, visitor), - visitLiteralExpressionOrTemplateExpression(context, (node).template, visitor)); + visitNode(context, (node).tag, visitor), + visitNode(context, (node).template, visitor))); case SyntaxKind.TypeAssertionExpression: - return factory.updateTypeAssertionExpression( + return write(factory.updateTypeAssertionExpression( node, - visitTypeNode(context, (node).type, visitor), - visitUnaryExpression(context, (node).expression, visitor)); + visitNode(context, (node).type, visitor), + visitNode(context, (node).expression, visitor))); case SyntaxKind.ParenthesizedExpression: - return factory.updateParenthesizedExpression( + return write(factory.updateParenthesizedExpression( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.FunctionExpression: - return factory.updateFunctionExpression( + return write(factory.updateFunctionExpression( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlockOrExpressionInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitBlockOrExpressionInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.ArrowFunction: - return factory.updateArrowFunction( + return write(factory.updateArrowFunction( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlockOrExpressionInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitBlockOrExpressionInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.DeleteExpression: - return factory.updateDeleteExpression( + return write(factory.updateDeleteExpression( node, - visitUnaryExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.TypeOfExpression: - return factory.updateTypeOfExpression( + return write(factory.updateTypeOfExpression( node, - visitUnaryExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.VoidExpression: - return factory.updateVoidExpression( + return write(factory.updateVoidExpression( node, - visitUnaryExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.AwaitExpression: - return factory.updateAwaitExpression( + return write(factory.updateAwaitExpression( node, - visitUnaryExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.PrefixUnaryExpression: - return factory.updatePrefixUnaryExpression( + return write(factory.updatePrefixUnaryExpression( node, - visitUnaryExpression(context, (node).operand, visitor)); + visitNode(context, (node).operand, visitor))); case SyntaxKind.PostfixUnaryExpression: - return factory.updatePostfixUnaryExpression( + return write(factory.updatePostfixUnaryExpression( node, - visitLeftHandSideExpression(context, (node).operand, visitor)); + visitNode(context, (node).operand, visitor))); case SyntaxKind.BinaryExpression: - return factory.updateBinaryExpression( + return write(factory.updateBinaryExpression( node, - visitExpression(context, (node).left, visitor), - visitExpression(context, (node).right, visitor)); + visitNode(context, (node).left, visitor), + visitNode(context, (node).right, visitor))); case SyntaxKind.ConditionalExpression: - return factory.updateConditionalExpression( + return write(factory.updateConditionalExpression( node, - visitExpression(context, (node).condition, visitor), - visitExpression(context, (node).whenTrue, visitor), - visitExpression(context, (node).whenFalse, visitor)); + visitNode(context, (node).condition, visitor), + visitNode(context, (node).whenTrue, visitor), + visitNode(context, (node).whenFalse, visitor))); case SyntaxKind.TemplateExpression: - return factory.updateTemplateExpression( + return write(factory.updateTemplateExpression( node, - visitLiteralExpression(context, (node).head, visitor), - visitNodeArrayOfTemplateSpan(context, (node).templateSpans, visitor)); + visitNode(context, (node).head, visitor), + >visitNodes(context, (node).templateSpans, visitor))); case SyntaxKind.YieldExpression: - return factory.updateYieldExpression( + return write(factory.updateYieldExpression( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.SpreadElementExpression: - return factory.updateSpreadElementExpression( + return write(factory.updateSpreadElementExpression( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.ClassExpression: - return factory.updateClassExpression( + return write(factory.updateClassExpression( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfHeritageClause(context, (node).heritageClauses, visitor), - visitNodeArrayOfClassElement(context, (node).members, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).heritageClauses, visitor), + >visitNodes(context, (node).members, visitor))); case SyntaxKind.ExpressionWithTypeArguments: - return factory.updateExpressionWithTypeArguments( + return write(factory.updateExpressionWithTypeArguments( node, - visitLeftHandSideExpression(context, (node).expression, visitor), - visitNodeArrayOfTypeNode(context, (node).typeArguments, visitor)); + visitNode(context, (node).expression, visitor), + >visitNodes(context, (node).typeArguments, visitor))); case SyntaxKind.AsExpression: - return factory.updateAsExpression( + return write(factory.updateAsExpression( node, - visitExpression(context, (node).expression, visitor), - visitTypeNode(context, (node).type, visitor)); + visitNode(context, (node).expression, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.TemplateSpan: - return factory.updateTemplateSpan( + return write(factory.updateTemplateSpan( node, - visitExpression(context, (node).expression, visitor), - visitLiteralExpression(context, (node).literal, visitor)); + visitNode(context, (node).expression, visitor), + visitNode(context, (node).literal, visitor))); case SyntaxKind.Block: - return factory.updateBlock( + return write(factory.updateBlock( node, - visitNodeArrayOfStatement(context, (node).statements, visitor)); + >visitNodes(context, (node).statements, visitor))); case SyntaxKind.VariableStatement: - return factory.updateVariableStatement( + return write(factory.updateVariableStatement( node, - visitVariableDeclarationList(context, (node).declarationList, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).declarationList, visitor))); case SyntaxKind.ExpressionStatement: - return factory.updateExpressionStatement( + return write(factory.updateExpressionStatement( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.IfStatement: - return factory.updateIfStatement( + return write(factory.updateIfStatement( node, - visitExpression(context, (node).expression, visitor), + visitNode(context, (node).expression, visitor), visitStatement(context, (node).thenStatement, visitor), - visitStatement(context, (node).elseStatement, visitor)); + visitStatement(context, (node).elseStatement, visitor))); case SyntaxKind.DoStatement: - return factory.updateDoStatement( + return write(factory.updateDoStatement( node, visitStatement(context, (node).statement, visitor), - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.WhileStatement: - return factory.updateWhileStatement( + return write(factory.updateWhileStatement( node, - visitExpression(context, (node).expression, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).expression, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.ForStatement: - return factory.updateForStatement( + return write(factory.updateForStatement( node, - visitExpressionOrVariableDeclarationList(context, (node).initializer, visitor), - visitExpression(context, (node).condition, visitor), - visitExpression(context, (node).incrementor, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).initializer, visitor), + visitNode(context, (node).condition, visitor), + visitNode(context, (node).incrementor, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.ForInStatement: - return factory.updateForInStatement( + return write(factory.updateForInStatement( node, - visitExpressionOrVariableDeclarationList(context, (node).initializer, visitor), - visitExpression(context, (node).expression, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).initializer, visitor), + visitNode(context, (node).expression, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.ForOfStatement: - return factory.updateForOfStatement( + return write(factory.updateForOfStatement( node, - visitExpressionOrVariableDeclarationList(context, (node).initializer, visitor), - visitExpression(context, (node).expression, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).initializer, visitor), + visitNode(context, (node).expression, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.ContinueStatement: - return factory.updateContinueStatement( + return write(factory.updateContinueStatement( node, - visitIdentifier(context, (node).label, visitor)); + visitNode(context, (node).label, visitor))); case SyntaxKind.BreakStatement: - return factory.updateBreakStatement( + return write(factory.updateBreakStatement( node, - visitIdentifier(context, (node).label, visitor)); + visitNode(context, (node).label, visitor))); case SyntaxKind.ReturnStatement: - return factory.updateReturnStatement( + return write(factory.updateReturnStatement( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.WithStatement: - return factory.updateWithStatement( + return write(factory.updateWithStatement( node, - visitExpression(context, (node).expression, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).expression, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.SwitchStatement: - return factory.updateSwitchStatement( + return write(factory.updateSwitchStatement( node, - visitExpression(context, (node).expression, visitor), - visitCaseBlock(context, (node).caseBlock, visitor)); + visitNode(context, (node).expression, visitor), + visitNode(context, (node).caseBlock, visitor))); case SyntaxKind.LabeledStatement: - return factory.updateLabeledStatement( + return write(factory.updateLabeledStatement( node, - visitIdentifier(context, (node).label, visitor), - visitStatement(context, (node).statement, visitor)); + visitNode(context, (node).label, visitor), + visitStatement(context, (node).statement, visitor))); case SyntaxKind.ThrowStatement: - return factory.updateThrowStatement( + return write(factory.updateThrowStatement( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.TryStatement: - return factory.updateTryStatement( + return write(factory.updateTryStatement( node, - visitBlock(context, (node).tryBlock, visitor), - visitCatchClause(context, (node).catchClause, visitor), - visitBlock(context, (node).finallyBlock, visitor)); + visitNode(context, (node).tryBlock, visitor), + visitNode(context, (node).catchClause, visitor), + visitNode(context, (node).finallyBlock, visitor))); case SyntaxKind.VariableDeclaration: - return factory.updateVariableDeclaration( + return write(factory.updateVariableDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitBindingPatternOrIdentifier(context, (node).name, visitor), - visitTypeNode(context, (node).type, visitor), - visitExpression(context, (node).initializer, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).type, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.VariableDeclarationList: - return factory.updateVariableDeclarationList( + return write(factory.updateVariableDeclarationList( node, - visitNodeArrayOfVariableDeclaration(context, (node).declarations, visitor)); + >visitNodes(context, (node).declarations, visitor))); case SyntaxKind.FunctionDeclaration: - return factory.updateFunctionDeclaration( + return write(factory.updateFunctionDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitTypeNode(context, (node).type, visitor), - visitBlockInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor), + visitBlockInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.ClassDeclaration: - return factory.updateClassDeclaration( + return write(factory.updateClassDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfHeritageClause(context, (node).heritageClauses, visitor), - visitNodeArrayOfClassElement(context, (node).members, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).heritageClauses, visitor), + >visitNodes(context, (node).members, visitor))); case SyntaxKind.InterfaceDeclaration: - return factory.updateInterfaceDeclaration( + return write(factory.updateInterfaceDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitNodeArrayOfHeritageClause(context, (node).heritageClauses, visitor), - visitNodeArrayOfTypeElement(context, (node).members, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + >visitNodes(context, (node).heritageClauses, visitor), + >visitNodes(context, (node).members, visitor))); case SyntaxKind.TypeAliasDeclaration: - return factory.updateTypeAliasDeclaration( + return write(factory.updateTypeAliasDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitTypeNode(context, (node).type, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeParameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.EnumDeclaration: - return factory.updateEnumDeclaration( + return write(factory.updateEnumDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitNodeArrayOfEnumMember(context, (node).members, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).members, visitor))); case SyntaxKind.ModuleDeclaration: - return factory.updateModuleDeclaration( + return write(factory.updateModuleDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifierOrLiteralExpression(context, (node).name, visitor), - visitModuleBlockOrModuleDeclarationInNewLexicalScope(context, (node).body, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + visitModuleBlockOrModuleDeclarationInNewLexicalEnvironment(context, (node).body, visitor))); case SyntaxKind.ModuleBlock: - return factory.updateModuleBlock( + return write(factory.updateModuleBlock( node, - visitNodeArrayOfStatement(context, (node).statements, visitor)); + >visitNodes(context, (node).statements, visitor))); case SyntaxKind.CaseBlock: - return factory.updateCaseBlock( + return write(factory.updateCaseBlock( node, - visitNodeArrayOfCaseOrDefaultClause(context, (node).clauses, visitor)); + >visitNodes(context, (node).clauses, visitor))); case SyntaxKind.ImportEqualsDeclaration: - return factory.updateImportEqualsDeclaration( + return write(factory.updateImportEqualsDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitIdentifier(context, (node).name, visitor), - visitEntityNameOrExternalModuleReference(context, (node).moduleReference, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).name, visitor), + visitNode(context, (node).moduleReference, visitor))); case SyntaxKind.ImportDeclaration: - return factory.updateImportDeclaration( + return write(factory.updateImportDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitImportClause(context, (node).importClause, visitor), - visitExpression(context, (node).moduleSpecifier, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).importClause, visitor), + visitNode(context, (node).moduleSpecifier, visitor))); case SyntaxKind.ImportClause: - return factory.updateImportClause( + return write(factory.updateImportClause( node, - visitIdentifier(context, (node).name, visitor), - visitNamedImportsOrNamespaceImport(context, (node).namedBindings, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).namedBindings, visitor))); case SyntaxKind.NamespaceImport: - return factory.updateNamespaceImport( + return write(factory.updateNamespaceImport( node, - visitIdentifier(context, (node).name, visitor)); + visitNode(context, (node).name, visitor))); case SyntaxKind.NamedImports: - return factory.updateNamedImports( + return write(factory.updateNamedImports( node, - visitNodeArrayOfImportOrExportSpecifier(context, (node).elements, visitor)); + >visitNodes(context, (node).elements, visitor))); case SyntaxKind.ImportSpecifier: - return factory.updateImportSpecifier( + return write(factory.updateImportSpecifier( node, - visitIdentifier(context, (node).propertyName, visitor), - visitIdentifier(context, (node).name, visitor)); + visitNode(context, (node).propertyName, visitor), + visitNode(context, (node).name, visitor))); case SyntaxKind.ExportAssignment: - return factory.updateExportAssignment( + return write(factory.updateExportAssignment( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitExpression(context, (node).expression, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).expression, visitor))); case SyntaxKind.ExportDeclaration: - return factory.updateExportDeclaration( + return write(factory.updateExportDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor), - visitNamedExports(context, (node).exportClause, visitor), - visitExpression(context, (node).moduleSpecifier, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor), + visitNode(context, (node).exportClause, visitor), + visitNode(context, (node).moduleSpecifier, visitor))); case SyntaxKind.NamedExports: - return factory.updateNamedExports( + return write(factory.updateNamedExports( node, - visitNodeArrayOfImportOrExportSpecifier(context, (node).elements, visitor)); + >visitNodes(context, (node).elements, visitor))); case SyntaxKind.ExportSpecifier: - return factory.updateExportSpecifier( + return write(factory.updateExportSpecifier( node, - visitIdentifier(context, (node).propertyName, visitor), - visitIdentifier(context, (node).name, visitor)); + visitNode(context, (node).propertyName, visitor), + visitNode(context, (node).name, visitor))); case SyntaxKind.MissingDeclaration: - return factory.updateMissingDeclaration( + return write(factory.updateMissingDeclaration( node, - visitNodeArrayOfDecorator(context, (node).decorators, visitor), - visitNodeArrayOfModifier(context, (node).modifiers, visitor)); + >visitNodes(context, (node).decorators, visitor), + >visitNodes(context, (node).modifiers, visitor))); case SyntaxKind.ExternalModuleReference: - return factory.updateExternalModuleReference( + return write(factory.updateExternalModuleReference( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.JsxElement: - return factory.updateJsxElement( + return write(factory.updateJsxElement( node, - visitJsxOpeningElement(context, (node).openingElement, visitor), - visitNodeArrayOfJsxChild(context, (node).children, visitor), - visitJsxClosingElement(context, (node).closingElement, visitor)); + visitNode(context, (node).openingElement, visitor), + >visitNodes(context, (node).children, visitor), + visitNode(context, (node).closingElement, visitor))); case SyntaxKind.JsxSelfClosingElement: - return factory.updateJsxSelfClosingElement( + return write(factory.updateJsxSelfClosingElement( node, - visitEntityName(context, (node).tagName, visitor), - visitNodeArrayOfJsxAttributeOrJsxSpreadAttribute(context, (node).attributes, visitor)); + visitNode(context, (node).tagName, visitor), + >visitNodes(context, (node).attributes, visitor))); case SyntaxKind.JsxOpeningElement: - return factory.updateJsxOpeningElement( + return write(factory.updateJsxOpeningElement( node, - visitEntityName(context, (node).tagName, visitor), - visitNodeArrayOfJsxAttributeOrJsxSpreadAttribute(context, (node).attributes, visitor)); + visitNode(context, (node).tagName, visitor), + >visitNodes(context, (node).attributes, visitor))); case SyntaxKind.JsxClosingElement: - return factory.updateJsxClosingElement( + return write(factory.updateJsxClosingElement( node, - visitEntityName(context, (node).tagName, visitor)); + visitNode(context, (node).tagName, visitor))); case SyntaxKind.JsxAttribute: - return factory.updateJsxAttribute( + return write(factory.updateJsxAttribute( node, - visitIdentifier(context, (node).name, visitor), - visitExpression(context, (node).initializer, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.JsxSpreadAttribute: - return factory.updateJsxSpreadAttribute( + return write(factory.updateJsxSpreadAttribute( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.JsxExpression: - return factory.updateJsxExpression( + return write(factory.updateJsxExpression( node, - visitExpression(context, (node).expression, visitor)); + visitNode(context, (node).expression, visitor))); case SyntaxKind.CaseClause: - return factory.updateCaseClause( + return write(factory.updateCaseClause( node, - visitExpression(context, (node).expression, visitor), - visitNodeArrayOfStatement(context, (node).statements, visitor)); + visitNode(context, (node).expression, visitor), + >visitNodes(context, (node).statements, visitor))); case SyntaxKind.DefaultClause: - return factory.updateDefaultClause( + return write(factory.updateDefaultClause( node, - visitNodeArrayOfStatement(context, (node).statements, visitor)); + >visitNodes(context, (node).statements, visitor))); case SyntaxKind.HeritageClause: - return factory.updateHeritageClause( + return write(factory.updateHeritageClause( node, - visitNodeArrayOfExpressionWithTypeArguments(context, (node).types, visitor)); + >visitNodes(context, (node).types, visitor))); case SyntaxKind.CatchClause: - return factory.updateCatchClause( + return write(factory.updateCatchClause( node, - visitVariableDeclaration(context, (node).variableDeclaration, visitor), - visitBlock(context, (node).block, visitor)); + visitNode(context, (node).variableDeclaration, visitor), + visitNode(context, (node).block, visitor))); case SyntaxKind.PropertyAssignment: - return factory.updatePropertyAssignment( + return write(factory.updatePropertyAssignment( node, - visitPropertyName(context, (node).name, visitor), - visitExpression(context, (node).initializer, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.ShorthandPropertyAssignment: - return factory.updateShorthandPropertyAssignment( + return write(factory.updateShorthandPropertyAssignment( node, - visitIdentifier(context, (node).name, visitor)); + visitNode(context, (node).name, visitor))); case SyntaxKind.EnumMember: - return factory.updateEnumMember( + return write(factory.updateEnumMember( node, - visitDeclarationName(context, (node).name, visitor), - visitExpression(context, (node).initializer, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).initializer, visitor))); case SyntaxKind.JSDocTypeExpression: - return factory.updateJSDocTypeExpression( + return write(factory.updateJSDocTypeExpression( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocArrayType: - return factory.updateJSDocArrayType( + return write(factory.updateJSDocArrayType( node, - visitJSDocType(context, (node).elementType, visitor)); + visitNode(context, (node).elementType, visitor))); case SyntaxKind.JSDocUnionType: - return factory.updateJSDocUnionType( + return write(factory.updateJSDocUnionType( node, - visitNodeArrayOfJSDocType(context, (node).types, visitor)); + >visitNodes(context, (node).types, visitor))); case SyntaxKind.JSDocTupleType: - return factory.updateJSDocTupleType( + return write(factory.updateJSDocTupleType( node, - visitNodeArrayOfJSDocType(context, (node).types, visitor)); + >visitNodes(context, (node).types, visitor))); case SyntaxKind.JSDocNullableType: - return factory.updateJSDocNullableType( + return write(factory.updateJSDocNullableType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocNonNullableType: - return factory.updateJSDocNonNullableType( + return write(factory.updateJSDocNonNullableType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocRecordType: - return factory.updateJSDocRecordType( + return write(factory.updateJSDocRecordType( node, - visitNodeArrayOfJSDocRecordMember(context, (node).members, visitor)); + >visitNodes(context, (node).members, visitor))); case SyntaxKind.JSDocRecordMember: - return factory.updateJSDocRecordMember( + return write(factory.updateJSDocRecordMember( node, - visitIdentifierOrLiteralExpression(context, (node).name, visitor), - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).name, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocTypeReference: - return factory.updateJSDocTypeReference( + return write(factory.updateJSDocTypeReference( node, - visitEntityName(context, (node).name, visitor), - visitNodeArrayOfJSDocType(context, (node).typeArguments, visitor)); + visitNode(context, (node).name, visitor), + >visitNodes(context, (node).typeArguments, visitor))); case SyntaxKind.JSDocOptionalType: - return factory.updateJSDocOptionalType( + return write(factory.updateJSDocOptionalType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocFunctionType: - return factory.updateJSDocFunctionType( + return write(factory.updateJSDocFunctionType( node, - visitNodeArrayOfParameter(context, (node).parameters, visitor), - visitJSDocType(context, (node).type, visitor)); + >visitNodes(context, (node).parameters, visitor), + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocVariadicType: - return factory.updateJSDocVariadicType( + return write(factory.updateJSDocVariadicType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocConstructorType: - return factory.updateJSDocConstructorType( + return write(factory.updateJSDocConstructorType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocThisType: - return factory.updateJSDocThisType( + return write(factory.updateJSDocThisType( node, - visitJSDocType(context, (node).type, visitor)); + visitNode(context, (node).type, visitor))); case SyntaxKind.JSDocComment: - return factory.updateJSDocComment( + return write(factory.updateJSDocComment( node, - visitNodeArrayOfJSDocTag(context, (node).tags, visitor)); + >visitNodes(context, (node).tags, visitor))); case SyntaxKind.JSDocTag: - return factory.updateJSDocTag( + return write(factory.updateJSDocTag( node, - visitIdentifier(context, (node).tagName, visitor)); + visitNode(context, (node).tagName, visitor))); case SyntaxKind.JSDocParameterTag: - return factory.updateJSDocParameterTag( + return write(factory.updateJSDocParameterTag( node, - visitIdentifier(context, (node).preParameterName, visitor), - visitJSDocTypeExpression(context, (node).typeExpression, visitor), - visitIdentifier(context, (node).postParameterName, visitor), - visitIdentifier(context, (node).tagName, visitor)); + visitNode(context, (node).preParameterName, visitor), + visitNode(context, (node).typeExpression, visitor), + visitNode(context, (node).postParameterName, visitor), + visitNode(context, (node).tagName, visitor))); case SyntaxKind.JSDocReturnTag: - return factory.updateJSDocReturnTag( + return write(factory.updateJSDocReturnTag( node, - visitJSDocTypeExpression(context, (node).typeExpression, visitor), - visitIdentifier(context, (node).tagName, visitor)); + visitNode(context, (node).typeExpression, visitor), + visitNode(context, (node).tagName, visitor))); case SyntaxKind.JSDocTypeTag: - return factory.updateJSDocTypeTag( + return write(factory.updateJSDocTypeTag( node, - visitJSDocTypeExpression(context, (node).typeExpression, visitor), - visitIdentifier(context, (node).tagName, visitor)); + visitNode(context, (node).typeExpression, visitor), + visitNode(context, (node).tagName, visitor))); case SyntaxKind.JSDocTemplateTag: - return factory.updateJSDocTemplateTag( + return write(factory.updateJSDocTemplateTag( node, - visitNodeArrayOfTypeParameter(context, (node).typeParameters, visitor), - visitIdentifier(context, (node).tagName, visitor)); + >visitNodes(context, (node).typeParameters, visitor), + visitNode(context, (node).tagName, visitor))); default: - return node; + return write(node); } } - export function visitEntityName(context: VisitorContext, node: EntityName, visitor: Visitor): EntityName { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isEntityName(visited), "Wrong node kind after visit."); - return visited; - } - export function visitIdentifier(context: VisitorContext, node: Identifier, visitor: Visitor): Identifier { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isIdentifier(visited), "Wrong node kind after visit."); - return visited; - } - export function visitExpression(context: VisitorContext, node: Expression, visitor: Visitor): Expression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitLeftHandSideExpression(context: VisitorContext, node: LeftHandSideExpression, visitor: Visitor): LeftHandSideExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isLeftHandSideExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitTypeNode(context: VisitorContext, node: TypeNode, visitor: Visitor): TypeNode { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isTypeNode(visited), "Wrong node kind after visit."); - return visited; - } - export function visitTypeParameter(context: VisitorContext, node: TypeParameterDeclaration, visitor: Visitor): TypeParameterDeclaration { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isTypeParameter(visited), "Wrong node kind after visit."); - return visited; - } - export function visitParameter(context: VisitorContext, node: ParameterDeclaration, visitor: Visitor): ParameterDeclaration { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isParameter(visited), "Wrong node kind after visit."); - return visited; - } - export function visitBindingPatternOrIdentifier(context: VisitorContext, node: BindingPattern | Identifier, visitor: Visitor): BindingPattern | Identifier { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isBindingPatternOrIdentifier(visited), "Wrong node kind after visit."); - return visited; - } - export function visitDecorator(context: VisitorContext, node: Decorator, visitor: Visitor): Decorator { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isDecorator(visited), "Wrong node kind after visit."); - return visited; - } - export function visitModifier(context: VisitorContext, node: Modifier, visitor: Visitor): Modifier { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isModifier(visited), "Wrong node kind after visit."); - return visited; - } - export function visitVariableDeclaration(context: VisitorContext, node: VariableDeclaration, visitor: Visitor): VariableDeclaration { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isVariableDeclaration(visited), "Wrong node kind after visit."); - return visited; - } - export function visitPropertyName(context: VisitorContext, node: PropertyName, visitor: Visitor): PropertyName { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isPropertyName(visited), "Wrong node kind after visit."); - return visited; - } - export function visitBindingElement(context: VisitorContext, node: BindingElement, visitor: Visitor): BindingElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isBindingElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitBlock(context: VisitorContext, node: Block, visitor: Visitor): Block { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isBlock(visited), "Wrong node kind after visit."); - return visited; - } - export function visitTypeElement(context: VisitorContext, node: TypeElement, visitor: Visitor): TypeElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isTypeElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitUnaryExpression(context: VisitorContext, node: UnaryExpression, visitor: Visitor): UnaryExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isUnaryExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitBlockOrExpression(context: VisitorContext, node: Block | Expression, visitor: Visitor): Block | Expression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isBlockOrExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitLiteralExpression(context: VisitorContext, node: LiteralExpression, visitor: Visitor): LiteralExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isLiteralExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitTemplateSpan(context: VisitorContext, node: TemplateSpan, visitor: Visitor): TemplateSpan { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isTemplateSpan(visited), "Wrong node kind after visit."); - return visited; - } - export function visitObjectLiteralElement(context: VisitorContext, node: ObjectLiteralElement, visitor: Visitor): ObjectLiteralElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isObjectLiteralElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitLiteralExpressionOrTemplateExpression(context: VisitorContext, node: LiteralExpression | TemplateExpression, visitor: Visitor): LiteralExpression | TemplateExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isLiteralExpressionOrTemplateExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJsxOpeningElement(context: VisitorContext, node: JsxOpeningElement, visitor: Visitor): JsxOpeningElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJsxOpeningElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJsxChild(context: VisitorContext, node: JsxChild, visitor: Visitor): JsxChild { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJsxChild(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJsxClosingElement(context: VisitorContext, node: JsxClosingElement, visitor: Visitor): JsxClosingElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJsxClosingElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJsxAttributeOrJsxSpreadAttribute(context: VisitorContext, node: JsxAttribute | JsxSpreadAttribute, visitor: Visitor): JsxAttribute | JsxSpreadAttribute { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJsxAttributeOrJsxSpreadAttribute(visited), "Wrong node kind after visit."); - return visited; - } - export function visitVariableDeclarationList(context: VisitorContext, node: VariableDeclarationList, visitor: Visitor): VariableDeclarationList { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isVariableDeclarationList(visited), "Wrong node kind after visit."); - return visited; - } - export function visitExpressionOrVariableDeclarationList(context: VisitorContext, node: Expression | VariableDeclarationList, visitor: Visitor): Expression | VariableDeclarationList { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isExpressionOrVariableDeclarationList(visited), "Wrong node kind after visit."); - return visited; - } - export function visitCaseBlock(context: VisitorContext, node: CaseBlock, visitor: Visitor): CaseBlock { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isCaseBlock(visited), "Wrong node kind after visit."); - return visited; - } - export function visitCaseOrDefaultClause(context: VisitorContext, node: CaseOrDefaultClause, visitor: Visitor): CaseOrDefaultClause { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isCaseOrDefaultClause(visited), "Wrong node kind after visit."); - return visited; - } - export function visitCatchClause(context: VisitorContext, node: CatchClause, visitor: Visitor): CatchClause { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isCatchClause(visited), "Wrong node kind after visit."); - return visited; - } - export function visitHeritageClause(context: VisitorContext, node: HeritageClause, visitor: Visitor): HeritageClause { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isHeritageClause(visited), "Wrong node kind after visit."); - return visited; - } - export function visitClassElement(context: VisitorContext, node: ClassElement, visitor: Visitor): ClassElement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isClassElement(visited), "Wrong node kind after visit."); - return visited; - } - export function visitExpressionWithTypeArguments(context: VisitorContext, node: ExpressionWithTypeArguments, visitor: Visitor): ExpressionWithTypeArguments { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isExpressionWithTypeArguments(visited), "Wrong node kind after visit."); - return visited; - } - export function visitDeclarationName(context: VisitorContext, node: DeclarationName, visitor: Visitor): DeclarationName { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isDeclarationName(visited), "Wrong node kind after visit."); - return visited; - } - export function visitEnumMember(context: VisitorContext, node: EnumMember, visitor: Visitor): EnumMember { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isEnumMember(visited), "Wrong node kind after visit."); - return visited; - } - export function visitIdentifierOrLiteralExpression(context: VisitorContext, node: Identifier | LiteralExpression, visitor: Visitor): Identifier | LiteralExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isIdentifierOrLiteralExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitModuleBlockOrModuleDeclaration(context: VisitorContext, node: ModuleBlock | ModuleDeclaration, visitor: Visitor): ModuleBlock | ModuleDeclaration { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isModuleBlockOrModuleDeclaration(visited), "Wrong node kind after visit."); - return visited; - } - export function visitEntityNameOrExternalModuleReference(context: VisitorContext, node: EntityName | ExternalModuleReference, visitor: Visitor): EntityName | ExternalModuleReference { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isEntityNameOrExternalModuleReference(visited), "Wrong node kind after visit."); - return visited; - } - export function visitImportClause(context: VisitorContext, node: ImportClause, visitor: Visitor): ImportClause { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isImportClause(visited), "Wrong node kind after visit."); - return visited; - } - export function visitNamedImportsOrNamespaceImport(context: VisitorContext, node: NamedImports | NamespaceImport, visitor: Visitor): NamedImports | NamespaceImport { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isNamedImportsOrNamespaceImport(visited), "Wrong node kind after visit."); - return visited; - } - export function visitNamedExports(context: VisitorContext, node: NamedExports, visitor: Visitor): NamedExports { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isNamedExports(visited), "Wrong node kind after visit."); - return visited; - } - export function visitImportOrExportSpecifier(context: VisitorContext, node: ImportOrExportSpecifier, visitor: Visitor): ImportOrExportSpecifier { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isImportOrExportSpecifier(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJSDocType(context: VisitorContext, node: JSDocType, visitor: Visitor): JSDocType { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJSDocType(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJSDocRecordMember(context: VisitorContext, node: JSDocRecordMember, visitor: Visitor): JSDocRecordMember { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJSDocRecordMember(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJSDocTag(context: VisitorContext, node: JSDocTag, visitor: Visitor): JSDocTag { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJSDocTag(visited), "Wrong node kind after visit."); - return visited; - } - export function visitJSDocTypeExpression(context: VisitorContext, node: JSDocTypeExpression, visitor: Visitor): JSDocTypeExpression { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isJSDocTypeExpression(visited), "Wrong node kind after visit."); - return visited; - } - export function visitNodeArrayOfTypeParameter(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitTypeParameter); - } - export function visitNodeArrayOfParameter(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitParameter); - } - export function visitNodeArrayOfDecorator(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitDecorator); - } - export function visitNodeArrayOfModifier(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitModifier); - } - export function visitNodeArrayOfVariableDeclaration(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitVariableDeclaration); - } - export function visitNodeArrayOfBindingElement(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitBindingElement); - } - export function visitNodeArrayOfTypeNode(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitTypeNode); - } - export function visitNodeArrayOfTypeElement(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitTypeElement); - } - export function visitNodeArrayOfTemplateSpan(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitTemplateSpan); - } - export function visitNodeArrayOfExpression(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitExpression); - } - export function visitNodeArrayOfObjectLiteralElement(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitObjectLiteralElement); - } - export function visitNodeArrayOfJsxChild(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitJsxChild); - } - export function visitNodeArrayOfJsxAttributeOrJsxSpreadAttribute(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitJsxAttributeOrJsxSpreadAttribute); - } - export function visitNodeArrayOfCaseOrDefaultClause(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitCaseOrDefaultClause); - } - export function visitNodeArrayOfHeritageClause(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitHeritageClause); - } - export function visitNodeArrayOfClassElement(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitClassElement); - } - export function visitNodeArrayOfExpressionWithTypeArguments(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitExpressionWithTypeArguments); - } - export function visitNodeArrayOfEnumMember(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitEnumMember); - } - export function visitNodeArrayOfImportOrExportSpecifier(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitImportOrExportSpecifier); - } - export function visitNodeArrayOfJSDocType(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitJSDocType); - } - export function visitNodeArrayOfJSDocRecordMember(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitJSDocRecordMember); - } - export function visitNodeArrayOfJSDocTag(context: VisitorContext, nodes: Array, visitor: Visitor): NodeArray { - return >visitNodes(context, nodes, visitor, visitJSDocTag); - } } diff --git a/src/compiler/transform.ts b/src/compiler/transform.ts index a44ec003b0a..89f5a122bc2 100644 --- a/src/compiler/transform.ts +++ b/src/compiler/transform.ts @@ -8,43 +8,399 @@ namespace ts.transform { CountMask = 0x0FFFFFFF, // Temp variable counter _i = 0x10000000, // Use/preference flag for '_i' } + + export function needsTransform(node: Node, mask: TransformFlags): boolean { + return !!(node.transformFlags & mask); + } + + let transformFlags: TransformFlags; + + export function aggregateTransformFlags(node: Node) { + if (!node) { + return; + } + + transformFlags = node.transformFlags; + if (transformFlags === undefined) { + transformFlags = 0; + aggregateTransformFlagsForNode(node); + node.transformFlags = transformFlags; + } + + transformFlags &= ~(TransformFlags.NodeExcludes | node.excludeTransformFlags); + } + + function aggregateTransformFlagsForChildNode(child: Node) { + let saveTransformFlags = transformFlags; + transformFlags = 0; + aggregateTransformFlags(child); + transformFlags = saveTransformFlags | transformFlags; + } + function aggregateTransformFlagsForNode(node: Node) { + forEachChild(node, aggregateTransformFlagsForChildNode); + + if (node.flags & NodeFlags.Ambient) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + // Mark transformations needed for each node + switch (node.kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.ModuleDeclaration: + node.excludeTransformFlags = TransformFlags.ModuleScopeExcludes; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TemplateExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + // case SyntaxKind.NumericLiteral: + // let sourceFile = getSourceFileOfNode(node); + // let firstChar = sourceFile.text.charCodeAt(node.pos); + // if (firstChar === CharacterCodes.b + // || firstChar === CharacterCodes.B + // || firstChar === CharacterCodes.o + // || firstChar === CharacterCodes.O) { + // markTransform(TransformFlags.ThisNodeIsES6); + // } + // break; + + case SyntaxKind.Parameter: + if ((node).questionToken) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + if ((node).flags & NodeFlags.AccessibilityModifier) { + transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; + } + if ((node).initializer) { + transformFlags |= TransformFlags.ThisNodeIsES6ParameterInitializer; + } + if ((node).dotDotDotToken) { + transformFlags |= TransformFlags.ThisNodeIsES6RestParameter; + } + break; + + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.CallExpression: + node.excludeTransformFlags = TransformFlags.CallOrArrayLiteralExcludes; + break; + + case SyntaxKind.YieldExpression: + transformFlags |= TransformFlags.ThisNodeIsES6Yield; + break; + + case SyntaxKind.AwaitExpression: + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.BinaryExpression: + if (isDestructuringAssignment(node)) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + + case SyntaxKind.TaggedTemplateExpression: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.ThisKeyword: + transformFlags |= TransformFlags.ThisNodeIsThisKeyword; + break; + + case SyntaxKind.SpreadElementExpression: + transformFlags |= TransformFlags.ThisNodeIsES6SpreadElement; + break; + + case SyntaxKind.ShorthandPropertyAssignment: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.ArrowFunction: + node.excludeTransformFlags = TransformFlags.ArrowFunctionScopeExcludes; + transformFlags |= TransformFlags.ThisNodeIsES6; + if (transformFlags & TransformFlags.SubtreeContainsLexicalThis) { + transformFlags |= TransformFlags.ThisNodeCapturesLexicalThis; + } + if (node.flags & NodeFlags.Async) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + break; + + case SyntaxKind.FunctionExpression: + node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes; + if ((node).asteriskToken + || transformFlags & TransformFlags.SubtreeContainsES6ParameterOrCapturedThis) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + if (node.flags & NodeFlags.Async) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + break; + + case SyntaxKind.FunctionDeclaration: + node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes; + transformFlags |= TransformFlags.ThisNodeIsHoistedDeclaration; + if (!(node).body + || node.flags & NodeFlags.Async) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + if ((node).asteriskToken + || node.flags & NodeFlags.Export + || transformFlags & TransformFlags.SubtreeContainsES6ParameterOrCapturedThis) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + break; + + case SyntaxKind.ForOfStatement: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.ReturnStatement: + transformFlags |= TransformFlags.ThisNodeIsCompletionStatement; + break; + + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + transformFlags |= TransformFlags.ThisNodeIsES6VariableBindingPattern; + break; + + case SyntaxKind.VariableDeclarationList: + transformFlags |= TransformFlags.ThisNodeIsHoistedDeclaration; + if (node.flags & (NodeFlags.Let | NodeFlags.Const)) { + transformFlags |= TransformFlags.ThisNodeIsES6LetOrConst; + } + break; + + case SyntaxKind.VariableStatement: + if (node.flags & NodeFlags.Export) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + break; + + case SyntaxKind.Decorator: + transformFlags |= TransformFlags.ThisNodeIsTypeScriptDecorator; + break; + + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + node.excludeTransformFlags = TransformFlags.ClassScopeExcludes; + transformFlags |= TransformFlags.ThisNodeIsES6; + if (transformFlags & TransformFlags.ContainsTypeScriptClassSyntaxExtension) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + break; + + case SyntaxKind.HeritageClause: + if ((node).token !== SyntaxKind.ExtendsKeyword) { + transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; + } + break; + + case SyntaxKind.ExpressionWithTypeArguments: + if ((node).typeArguments) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + break; + + case SyntaxKind.PropertyDeclaration: + transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; + break; + + case SyntaxKind.Constructor: + node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes; + if (!(node).body) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + break; + + case SyntaxKind.MethodDeclaration: + node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes; + if (!(node).body) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + transformFlags |= TransformFlags.ThisNodeIsES6; + + if (transformFlags & TransformFlags.ContainsTypeScriptDecorator + && isComputedPropertyName((node).name)) { + transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; + } + + if (node.flags & NodeFlags.Async) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes; + if (transformFlags & TransformFlags.ContainsTypeScriptDecorator + && isComputedPropertyName((node).name)) { + transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; + } + break; + + case SyntaxKind.EnumDeclaration: + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.ImportEqualsDeclaration: + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.ImportDeclaration: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.ExportAssignment: + if ((node).isExportEquals) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + else { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + break; + + case SyntaxKind.ExportDeclaration: + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + } + + node.transformFlags = transformFlags; + } + export class VisitorContext { private generatedNameSet: Map; private nodeToGeneratedName: string[]; - private computedPropertyNamesToGeneratedNames: Identifier [] = []; + private nodeToGeneratedIdentifier: Identifier[] = []; + private isPinnedOrTripleSlashCommentCallback = (comment: CommentRange) => this.isPinnedOrTripleSlashCommentWorker(comment); + + // lexical environment stack private tempFlagStack: number[] = []; private hoistedVariableDeclarationsStack: VariableDeclaration[][] = []; private hoistedFunctionDeclarationsStack: FunctionDeclaration[][] = []; - private statementsStack: Statement[][] = []; - private isPinnedOrTripleSlashComment = (comment: CommentRange) => this.isPinnedOrTripleSlashCommentWorker(comment); + + // node stack + private nodeStackSize: number = 0; + private ancestorStack: Node[] = []; public compilerOptions: CompilerOptions; + public languageVersion: ScriptTarget; public currentSourceFile: SourceFile; public resolver: EmitResolver; + public parentNode: Node; + public currentNode: Node; + public getAncestorOrSelfCallback: (offset: number) => Node; constructor(compilerOptions: CompilerOptions, currentSourceFile: SourceFile, resolver: EmitResolver, generatedNameSet: Map, nodeToGeneratedName: string[]) { this.compilerOptions = compilerOptions; + this.languageVersion = compilerOptions.target || ScriptTarget.ES3; this.currentSourceFile = currentSourceFile; this.resolver = resolver; this.generatedNameSet = generatedNameSet; this.nodeToGeneratedName = nodeToGeneratedName; + this.getAncestorOrSelfCallback = offset => this.peekNode(offset); } + public pushNode(node: Node): void { + Debug.assert(node !== undefined, "Incorrect node stack behavior during push. Argument `node` is undefined.") + Debug.assert(this.currentNode !== node, "Incorrect node stack behavior during push. Argument `node` is already the current node."); + Debug.assert(this.parentNode !== node, "Incorrect node stack behavior during push. Argument `node` is already the parent node."); + this.nodeStackSize++; + if (this.nodeStackSize > 2) { + this.ancestorStack.push(this.parentNode); + } + this.parentNode = this.currentNode; + this.currentNode = node; + } + + public popNode(): void { + this.currentNode = this.parentNode; + this.parentNode = this.nodeStackSize > 2 ? this.ancestorStack.pop() : undefined; + this.nodeStackSize--; + } + + public peekNode(offset: number): Node { + switch (offset) { + case 0: return this.currentNode; + case 1: return this.parentNode; + default: return this.nodeStackSize > 2 ? this.ancestorStack[this.nodeStackSize - 1 - offset] : undefined; + } + } + + public findAncestorNode(match: (node: Node) => node is T): T; + public findAncestorNode(match: (node: Node) => boolean): Node; + public findAncestorNode(match: (node: Node) => boolean) { + for (let i = 1; i < this.nodeStackSize; i++) { + let node = this.peekNode(i); + if (match(node)) { + return node; + } + } + return undefined; + } + + // Returns the node flags for the current node and all relevant parent nodes. This is done so that + // nodes like variable declarations and binding elements can return a view of their flags + // that includes the modifiers from their container. i.e. flags like export/declare aren't + // stored on the variable declaration directly, but on the containing variable statement + // (if it has one). Similarly, flags for let/const are store on the variable declaration + // list. By calling this function, all those flags are combined so that the client can treat + // the node as if it actually had those flags. + public getCombinedNodeFlags(): NodeFlags { + return getCombinedNodeFlags(this.currentNode, this.getAncestorOrSelfCallback, /*offset*/ 0); + } + public pushLexicalEnvironment(): void { this.tempFlagStack.push(0); this.hoistedVariableDeclarationsStack.push(undefined); this.hoistedFunctionDeclarationsStack.push(undefined); } - + public getHoistedVariableDeclarations(): VariableDeclaration[] { return this.hoistedVariableDeclarationsStack[this.hoistedVariableDeclarationsStack.length - 1]; } - + public getHoistedFunctionDeclarations(): FunctionDeclaration[] { return this.hoistedFunctionDeclarationsStack[this.hoistedFunctionDeclarationsStack.length - 1]; } + public hasHoistedDeclarations(): boolean { + return !!this.getHoistedVariableDeclarations() + || !!this.getHoistedFunctionDeclarations(); + } + + public writeHoistedDeclarations(statements: Statement[]) { + let hoistedVariableDeclarations = this.getHoistedVariableDeclarations(); + if (hoistedVariableDeclarations) { + let varDecls = factory.createVariableDeclarationList(hoistedVariableDeclarations); + let varStmt = factory.createVariableStatement2(varDecls); + statements.push(varStmt); + } + + let hoistedFunctionDeclarations = this.getHoistedFunctionDeclarations(); + if (hoistedFunctionDeclarations) { + statements.push(...hoistedFunctionDeclarations); + } + } + // 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. @@ -62,7 +418,7 @@ namespace ts.transform { tempFlags++; // Skip over 'i' and 'n' if (count !== 8 && count !== 13) { - let name = count < 26 + let name = count < 26 ? "_" + String.fromCharCode(CharacterCodes.a + count) : "_" + (count - 26); if (this.isUniqueName(name)) { @@ -72,7 +428,7 @@ namespace ts.transform { } } } - + // 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 @@ -94,7 +450,7 @@ namespace ts.transform { public getGeneratedNameForNode(node: Node) { let id = getNodeId(node); - return this.nodeToGeneratedName[id] || (this.nodeToGeneratedName[id] = unescapeIdentifier(this.generateNameForNode(node))); + return this.nodeToGeneratedIdentifier[id] || (this.nodeToGeneratedIdentifier[id] = factory.createIdentifier(this.getGeneratedNameTextForNode(node, id))); } public nodeHasGeneratedName(node: Node) { @@ -107,13 +463,11 @@ namespace ts.transform { public getDeclarationName(node: Declaration): DeclarationName; public getDeclarationName(node: Declaration): T | Identifier { let name = node.name; - if (name && !nodeIsSynthesized(name)) { - return factory.cloneNode(name); + if (name) { + return nodeIsSynthesized(name) ? name : factory.cloneNode(name); } else { - return factory.createIdentifier( - this.getGeneratedNameForNode(node) - ); + return this.getGeneratedNameForNode(node); } } @@ -125,34 +479,34 @@ namespace ts.transform { factory.createIdentifier("prototype") ); } - + return expression; } - + public createUniqueIdentifier(baseName: string): Identifier { let name = this.makeUniqueName(baseName); return factory.createIdentifier(name); } - - public createTempVariable(flags: TempFlags): Identifier { - let name = this.makeTempVariableName(flags); + + public createTempVariable(loopVariable: boolean): Identifier { + let name = this.makeTempVariableName(loopVariable ? TempFlags._i : TempFlags.Auto); return factory.createIdentifier(name); } - + public declareLocal(baseName?: string): Identifier { - let local = baseName + let local = baseName ? this.createUniqueIdentifier(baseName) - : this.createTempVariable(TempFlags.Auto); + : this.createTempVariable(/*loopVariable*/ false); this.hoistVariableDeclaration(local); return local; } - + public hoistVariableDeclaration(name: Identifier): void { let hoistedVariableDeclarations = this.getHoistedVariableDeclarations(); if (!hoistedVariableDeclarations) { this.hoistedVariableDeclarationsStack[this.hoistedVariableDeclarationsStack.length - 1] = hoistedVariableDeclarations = []; } - + hoistedVariableDeclarations.push(factory.createVariableDeclaration2(name)); } @@ -161,100 +515,62 @@ namespace ts.transform { if (!hoistedFunctionDeclarations) { this.hoistedFunctionDeclarationsStack[this.hoistedFunctionDeclarationsStack.length - 1] = hoistedFunctionDeclarations = []; } - + hoistedFunctionDeclarations.push(func); } - + public popLexicalEnvironment(): void { this.tempFlagStack.pop(); this.hoistedVariableDeclarationsStack.pop(); this.hoistedFunctionDeclarationsStack.pop(); } - - public pushStatements(): void { - this.statementsStack.push(undefined); - } - - public getStatements(): Statement[] { - return this.statementsStack[this.statementsStack.length - 1]; - } - - public emitStatement(statement: Statement) { - if (!statement) { - return; - } - - let statements = this.statementsStack[this.statementsStack.length - 1]; - if (!statements) { - this.statementsStack[this.statementsStack.length - 1] = statements = []; - } - - statements.push(statement); - } - - public emitStatements(statements: Statement[]) { - for (let statement of statements) { - this.emitStatement(statement); - } - } - - public emitExpressionStatement(expression: Expression, location?: TextRange) { - this.emitStatement(factory.createExpressionStatement(expression)); - } - - public emitExpressionStatements(expressions: Expression[]) { - for (let expression of expressions) { - this.emitExpressionStatement(expression); - } - } - - public emitReturnStatement(expression?: Expression, location?: TextRange) { - this.emitStatement(factory.createReturnStatement(expression, location)); - } - - public emitAssignmentStatement(left: Expression, right: Expression, location?: TextRange) { - this.emitStatement(factory.createAssignmentExpressionStatement(left, right, location)); - } - - public popStatements(): void { - this.statementsStack.pop(); - } public getLeadingCommentRanges(node: Node, onlyPinnedOrTripleSlashComments?: boolean) { let leadingCommentRanges: CommentRange[]; - + while (node && !leadingCommentRanges) { leadingCommentRanges = (node).leadingCommentRanges; if (!leadingCommentRanges && !nodeIsSynthesized(node)) { leadingCommentRanges = getLeadingCommentRangesOfNode(node, this.currentSourceFile); } - + node = node.original; } - + return this.filterComments(leadingCommentRanges, onlyPinnedOrTripleSlashComments); } - + public getTrailingCommentRanges(node: Node) { let trailingCommentRanges: CommentRange[]; - + while (node && !trailingCommentRanges) { trailingCommentRanges = (node).trailingCommentRanges; if (!trailingCommentRanges && !nodeIsSynthesized(node)) { trailingCommentRanges = getTrailingCommentRanges(this.currentSourceFile.text, node.pos); } - + node = node.original; } - + return trailingCommentRanges; } + + public childNodeStartPositionIsOnSameLine(parent: Node, child: Node) { + if (nodeIsSynthesized(child)) { + return !(child).startsOnNewLine; + } + if (nodeIsSynthesized(parent)) { + return false; + } + return getLineOfLocalPosition(this.currentSourceFile, skipTrivia(this.currentSourceFile.text, parent.pos)) === + getLineOfLocalPosition(this.currentSourceFile, skipTrivia(this.currentSourceFile.text, child.pos)); + } private filterComments(ranges: CommentRange[], onlyPinnedOrTripleSlashComments: boolean): CommentRange[] { // If we're removing comments, then we want to strip out all but the pinned or // triple slash comments. if (ranges && onlyPinnedOrTripleSlashComments) { - ranges = filter(ranges, this.isPinnedOrTripleSlashComment); + ranges = filter(ranges, this.isPinnedOrTripleSlashCommentCallback); if (ranges.length === 0) { return undefined; } @@ -262,7 +578,7 @@ namespace ts.transform { return ranges; } - + private isPinnedOrTripleSlashCommentWorker(comment: CommentRange) { if (this.currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) { return this.currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation; @@ -296,6 +612,10 @@ namespace ts.transform { return true; } + private getGeneratedNameTextForNode(node: Node, id: number) { + return this.nodeToGeneratedName[id] || (this.nodeToGeneratedName[id] = unescapeIdentifier(this.generateNameForNode(node))); + } + private generateNameForNode(node: Node) { switch (node.kind) { case SyntaxKind.Identifier: @@ -313,6 +633,7 @@ namespace ts.transform { case SyntaxKind.ClassExpression: return this.generateNameForClassExpression(); case SyntaxKind.ComputedPropertyName: + case SyntaxKind.Parameter: return this.makeTempVariableName(TempFlags.Auto); } } @@ -339,48 +660,227 @@ namespace ts.transform { } } - export type Visitor = (context: VisitorContext, node: Node) => Node; + // single node transform + let updatedNode: Node; + let writeOneNode: typeof writeOneNodeSlow; - export function visit(context: VisitorContext, node: Node, visitor: Visitor): Node { - if (!node || !visitor) { + // single statement transform + let updatedStatement: Statement; + let updatedBlock: Block; + let writeOneStatement: typeof writeOneStatementSlow; + + // multiple node transform + let originalNodes: Node[]; + let updatedNodes: Node[]; + let offsetWritten: number; + let writeOneNodeToNodeArray: typeof writeOneNodeToNodeArraySlow; + + function writeNode(node: Node) { + if (!node) { + return; + } + + aggregateTransformFlags(node); + writeOneNode(node); + } + + function writeOneNodeSlow(node: Node) { + updatedNode = node; + writeOneNode = writeOneNodeFast; + } + + function writeOneNodeFast(node: Node) { + Debug.fail("Node already written"); + } + + function writeStatement(node: Statement) { + if (!node) { + return; + } + + aggregateTransformFlags(node); + writeOneStatement(node); + } + + function writeOneStatementSlow(node: Statement) { + updatedStatement = node; + writeOneStatement = writeOneStatementModerate; + } + + function writeOneStatementModerate(node: Statement) { + updatedBlock = factory.createBlock([updatedStatement, node]); + writeOneStatement = writeOneStatementFast; + } + + function writeOneStatementFast(node: Statement) { + updatedBlock.statements.push(node); + } + + function writeNodeToNodeArray(node: Node) { + if (!node) { + return; + } + + aggregateTransformFlags(node); + writeOneNodeToNodeArray(node); + } + + function writeOneNodeToNodeArraySlow(node: Node) { + if (offsetWritten === originalNodes.length || originalNodes[offsetWritten] !== node) { + updatedNodes = originalNodes.slice(0, offsetWritten); + updatedNodes.push(node); + writeOneNodeToNodeArray = writeOneNodeToNodeArrayFast; + } + else { + offsetWritten++; + } + } + + function writeOneNodeToNodeArrayFast(node: Node) { + updatedNodes.push(node); + } + + export type Visitor = (context: VisitorContext, input: Node, write: (node: Node) => void) => void; + + export function visitNode(context: VisitorContext, node: T, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): T { + if (!node) { return node; } - let visited = visitor(context, node); - if (visited && visited !== node) { - aggregateTransformFlags(visited); - } + let savedUpdatedNode = updatedNode; + let savedWriteOneNode = writeOneNode; + updatedNode = undefined; + writeOneNode = writeOneNodeSlow; + + context.pushNode(node); + visitor(context, node, writeNode); + context.popNode(); + + let visited = updatedNode; + updatedNode = savedUpdatedNode; + writeOneNode = savedWriteOneNode; return visited; } - export function visitStatement(context: VisitorContext, node: Statement, visitor: Visitor): Statement { - let visited = visit(context, node, visitor); - Debug.assert(!visited || isStatement(visited) || isDeclarationStatement(visited), "Wrong node kind after visit."); - return visited; - } + export function visitStatement(context: VisitorContext, node: Statement, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void) { + if (!node) { + return node; + } + + let savedUpdatedStatement = updatedStatement; + let savedUpdatedBlock = updatedBlock; + let savedWriteOneStatement = writeOneStatement; + updatedStatement = undefined; + updatedBlock = undefined; + writeOneStatement = writeOneStatementSlow; + context.pushNode(node); + visitor(context, node, writeStatement); + context.popNode(); + + let visited = updatedBlock || updatedStatement; + updatedStatement = savedUpdatedStatement; + updatedBlock = savedUpdatedBlock; + writeOneStatement = savedWriteOneStatement; + + return visited; + } + + export function visitNodes(context: VisitorContext, nodes: T[], visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): NodeArray { + if (!nodes) { + return nodes ? factory.createNodeArray(nodes) : undefined; + } + + let savedOriginalNodes = originalNodes; + let savedUpdatedNodes = updatedNodes; + let savedOffsetWritten = offsetWritten; + let savedWriteOneNodeToNodeArray = writeOneNodeToNodeArray; + originalNodes = nodes; + updatedNodes = undefined; + offsetWritten = 0; + writeOneNodeToNodeArray = writeOneNodeToNodeArraySlow; + + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i]; + context.pushNode(node); + visitor(context, node, writeNodeToNodeArray); + context.popNode(); + } + + let visited: NodeArray; + if (updatedNodes) { + visited = factory.createNodeArray(updatedNodes, /*location*/ >originalNodes); + } + else if (offsetWritten !== originalNodes.length) { + visited = factory.createNodeArray(originalNodes.slice(0, offsetWritten), /*location*/ >originalNodes); + } + else { + visited = factory.createNodeArray(originalNodes); + } + + originalNodes = savedOriginalNodes; + updatedNodes = savedUpdatedNodes; + offsetWritten = savedOffsetWritten; + writeOneNodeToNodeArray = savedWriteOneNodeToNodeArray; + return >visited; + + // let updatedNodes: T[]; + // //let cacheOffset = 0; + // for (var i = 0; i < nodes.length; i++) { + // let node = nodes[i]; + // // if (cache && cache.shouldCachePreviousNodes(node)) { + // // if (!updatedNodes) { + // // updatedNodes = nodes.slice(0, i); + // // } + + // // while (cacheOffset < updatedIndex) { + // // updatedNodes[cacheOffset] = cache.cacheNode(updatedNodes[cacheOffset]); + // // cacheOffset++; + // // } + + // // cacheOffset = updatedIndex; + // // } + + // let updatedNode = visitNode(context, node, visitor); + // if (updatedNodes || !updatedNode || updatedNode !== node) { + // if (!updatedNodes) { + // updatedNodes = nodes.slice(0, i); + // } + // if (updatedNode) { + // if (isSynthesizedList(updatedNode)) { + // let synthesizedList = >updatedNode; + // flattenSynthesizedList(synthesizedList, updatedNodes); + // } + // else { + // updatedNodes.push(updatedNode); + // } + // } + // } + // } + } + /** * Visits a Block in a new lexical scope. */ - export function visitBlockInNewLexicalScope(context: VisitorContext, node: Block, visitor: Visitor): Block { + export function visitBlockInNewLexicalEnvironment(context: VisitorContext, node: Block, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): Block { return visitNodeInNewLexicalEnvironment(context, node, visitor, afterVisitBlockInNewLexicalEnvironment); } - + /** * Visits a Block or an Expression that starts a new lexical scope. */ - export function visitBlockOrExpressionInNewLexicalScope(context: VisitorContext, node: Block | Expression, visitor: Visitor): Block | Expression { + export function visitBlockOrExpressionInNewLexicalEnvironment(context: VisitorContext, node: Block | Expression, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): Block | Expression { return visitNodeInNewLexicalEnvironment(context, node, visitor, afterVisitBlockOrExpressionInNewLexicalEnvironment); } - + /** * Visits a ModuleBlock or a ModuleDeclaration in a new lexical scope. */ - export function visitModuleBlockOrModuleDeclarationInNewLexicalScope(context: VisitorContext, node: ModuleBlock | ModuleDeclaration, visitor: Visitor): ModuleBlock | ModuleDeclaration { + export function visitModuleBlockOrModuleDeclarationInNewLexicalEnvironment(context: VisitorContext, node: ModuleBlock | ModuleDeclaration, visitor: (context: VisitorContext, input: Node, write: (node: Node) => void) => void): ModuleBlock | ModuleDeclaration { return visitNodeInNewLexicalEnvironment(context, node, visitor, afterVisitModuleBlockOrModuleDeclarationInNewLexicalEnvironment); } - + /** * Visits a node that starts a new lexical environment. */ @@ -399,35 +899,35 @@ namespace ts.transform { // untyped and could return any `Node` subtype. The `afterVisit` callback is also // used to specialize how hoisted declarations should be merged into the visited // node. - + // Save and reset temp flags and hoisted declarations for the lexical environment context.pushLexicalEnvironment(); - + // Visit the block or expression - let visited = visit(context, node, visitor); + let visited = visitNode(context, node, visitor); // If the visited node differs from the original node, or we declared new hoisted // declarations in this lexical environment, we should call the `afterVisit` callback. let hoistedVariableDeclarations = context.getHoistedVariableDeclarations(); let hoistedFunctionDeclarations = context.getHoistedFunctionDeclarations(); if (!visited || visited !== node || hoistedVariableDeclarations || hoistedFunctionDeclarations) { - // If there were any new hoisted declarations added in this lexical environment, we should + // If there were any new hoisted declarations added in this lexical environment, we should // include them in the statments we pass to the `afterVisit` callback. let statements: Statement[]; if (hoistedVariableDeclarations || hoistedFunctionDeclarations) { statements = []; if (hoistedVariableDeclarations) { - statements.push(factory.createVariableStatement(factory.createVariableDeclarationList(hoistedVariableDeclarations))); + statements.push(factory.createVariableStatement2(factory.createVariableDeclarationList(hoistedVariableDeclarations))); } if (hoistedFunctionDeclarations) { statements.push(...hoistedFunctionDeclarations); } } - + // Perform any assertions and merge generated statements with the visited node. visited = afterVisit(visited, statements); } - + // Restore temp flags and hoisted declarations from the caller context.popLexicalEnvironment(); return visited; @@ -435,7 +935,7 @@ namespace ts.transform { function afterVisitBlockInNewLexicalEnvironment(visited: Block, statements: Statement[]): Block { Debug.assert(!visited || isBlock(visited), "Wrong node kind after visit."); - + let merged: Block; if (statements) { if (visited) { @@ -448,13 +948,13 @@ namespace ts.transform { merged = factory.createBlock(statements); } } - + return merged || visited; } function afterVisitBlockOrExpressionInNewLexicalEnvironment(visited: Block | Expression, statements: Statement[]): Block | Expression { Debug.assert(!visited || isBlock(visited) || isExpression(visited), "Wrong node kind after visit."); - + let merged: Block | Expression; if (statements) { if (visited) { @@ -475,13 +975,13 @@ namespace ts.transform { merged = factory.createBlock(statements); } } - + return merged || visited; } - + function afterVisitModuleBlockOrModuleDeclarationInNewLexicalEnvironment(visited: ModuleBlock | ModuleDeclaration, statements: Statement[]): ModuleBlock | ModuleDeclaration { Debug.assert(!visited || isModuleBlock(visited) || isModuleDeclaration(visited), "Wrong node kind after visit."); - + let merged: ModuleBlock | ModuleDeclaration; if (statements) { if (visited) { @@ -502,341 +1002,7 @@ namespace ts.transform { merged = factory.createModuleBlock(statements); } } - + return merged || visited; } - - export function visitNodes(context: VisitorContext, nodes: T[], visitor: Visitor, visitNode: (context: VisitorContext, node: Node, visitor: Visitor) => T): T[] { - if (!nodes || !visitor) { - return nodes; - } - - let updatedNodes: T[]; - //let cacheOffset = 0; - for (var i = 0; i < nodes.length; i++) { - let node = nodes[i]; - // if (cache && cache.shouldCachePreviousNodes(node)) { - // if (!updatedNodes) { - // updatedNodes = nodes.slice(0, i); - // } - - // while (cacheOffset < updatedIndex) { - // updatedNodes[cacheOffset] = cache.cacheNode(updatedNodes[cacheOffset]); - // cacheOffset++; - // } - - // cacheOffset = updatedIndex; - // } - - let updatedNode = visitNode(context, node, visitor); - if (updatedNodes || !updatedNode || updatedNode !== node) { - if (!updatedNodes) { - updatedNodes = nodes.slice(0, i); - } - if (updatedNode) { - updatedNodes.push(updatedNode); - } - } - } - - if (updatedNodes) { - return factory.createNodeArray(updatedNodes, /*location*/ >nodes); - } - - return nodes; - } - - - export function visitNodeArrayOfStatement(context: VisitorContext, statements: NodeArray, visitor: Visitor): NodeArray { - return visitNodeArrayWithStack(context, statements, visitor, visitStatement, pushStatementContext, popStatementContext, getContextStatements); - } - - function visitNodeArrayWithStack(context: VisitorContext, nodes: NodeArray, visitor: Visitor, - visitNode: (context: VisitorContext, node: T, visitor: Visitor) => T, pushContext: (context: VisitorContext) => void, - popContext: (context: VisitorContext) => void, getGeneratedNodes: (context: VisitorContext) => T[]): NodeArray { - if (!nodes || !visitor) { - return nodes; - } - - pushContext(context); - - let updatedNodes: T[]; - let contextNodes: T[]; - let contextNodesOffset = 0; - for (let i = 0; i < nodes.length; i++) { - let node = nodes[i]; - let updatedNode = visitNode(context, node, visitor); - if (updatedNodes || !updatedNode || updatedNode !== node) { - if (!updatedNodes) { - updatedNodes = nodes.slice(0, i); - } - if (contextNodes || (contextNodes = getGeneratedNodes(context))) { - while (contextNodesOffset < contextNodes.length) { - let contextNode = contextNodes[contextNodesOffset++]; - if (contextNode) { - transform.aggregateTransformFlags(contextNode); - updatedNodes.push(contextNode); - } - } - } - if (updatedNode) { - updatedNodes.push(updatedNode); - } - } - } - - popContext(context); - - return updatedNodes - ? factory.createNodeArray(updatedNodes, /*location*/ nodes) - : nodes; - } - - function pushStatementContext(context: VisitorContext) { - context.pushStatements(); - } - - function popStatementContext(context: VisitorContext) { - context.popStatements(); - } - - function getContextStatements(context: VisitorContext) { - return context.getStatements(); - } - - export function needsTransform(node: Node, mask: TransformFlags): boolean { - return !!(node.transformFlags & mask); - } - - let transformFlags: TransformFlags; - - function aggregateChildTransformFlags(child: Node) { - let saveTransformFlags = transformFlags; - aggregateTransformFlags(child); - transformFlags = saveTransformFlags | (transformFlags & ~TransformFlags.ThisNodeFlags); - } - - export function aggregateTransformFlags(node: Node) { - transformFlags = node.transformFlags; - if (transformFlags === undefined) { - forEachChild(node, aggregateChildTransformFlags); - - if (node.flags & NodeFlags.Ambient) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptAmbientDeclaration; - } - - // Mark transformations needed for each node - switch (node.kind) { - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.AbstractKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.ConstKeyword: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptAccessibilityModifier - break; - - case SyntaxKind.ModuleDeclaration: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptModuleDeclaration; - break; - - case SyntaxKind.ComputedPropertyName: - transformFlags |= TransformFlags.ThisNodeIsES6ComputedPropertyName; - break; - - case SyntaxKind.TemplateExpression: - transformFlags |= TransformFlags.ThisNodeIsES6TemplateExpression; - break; - - case SyntaxKind.NoSubstitutionTemplateLiteral: - transformFlags |= TransformFlags.ThisNodeIsES6NoSubstitutionTemplateLiteral; - break; - - // case SyntaxKind.NumericLiteral: - // let sourceFile = getSourceFileOfNode(node); - // let firstChar = sourceFile.text.charCodeAt(node.pos); - // if (firstChar === CharacterCodes.b - // || firstChar === CharacterCodes.B - // || firstChar === CharacterCodes.o - // || firstChar === CharacterCodes.O) { - // markTransform(TransformFlags.ThisNodeIsES6BinaryOrOctalLiteralExpression); - // } - // break; - - case SyntaxKind.Parameter: - if ((node).questionToken) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptOptionalParameter; - } - if ((node).flags & NodeFlags.AccessibilityModifier) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptParameterPropertyAssignment; - } - if ((node).initializer) { - transformFlags |= TransformFlags.ThisNodeIsES6ParameterInitializer; - } - if ((node).dotDotDotToken) { - transformFlags |= TransformFlags.ThisNodeIsES6RestParameter; - } - break; - - case SyntaxKind.YieldExpression: - transformFlags |= TransformFlags.ThisNodeIsES6Yield; - break; - - case SyntaxKind.BinaryExpression: - if (isDestructuringAssignment(node)) { - transformFlags |= TransformFlags.ThisNodeIsES6DestructuringAssignment; - } - break; - - case SyntaxKind.TaggedTemplateExpression: - transformFlags |= TransformFlags.ThisNodeIsES6TaggedTemplateExpression; - break; - - case SyntaxKind.ThisKeyword: - transformFlags |= TransformFlags.ThisNodeIsThisKeyword; - break; - - case SyntaxKind.SpreadElementExpression: - transformFlags |= TransformFlags.ThisNodeIsES6SpreadElement; - break; - - case SyntaxKind.ShorthandPropertyAssignment: - transformFlags |= TransformFlags.ThisNodeIsES6ShorthandPropertyAssignment; - break; - - case SyntaxKind.ArrowFunction: - transformFlags |= TransformFlags.ThisNodeIsES6ArrowFunction; - break; - - case SyntaxKind.FunctionExpression: - if ((node).asteriskToken) { - transformFlags |= TransformFlags.ThisNodeIsES6Generator; - } - break; - - case SyntaxKind.FunctionDeclaration: - if (!(node).body) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptOverload; - } - - if ((node).asteriskToken) { - transformFlags |= TransformFlags.ThisNodeIsES6Generator; - } - if (node.parserContextFlags & ParserContextFlags.Yield) { - transformFlags |= TransformFlags.ThisNodeIsHoistedDeclarationInGenerator; - } - if (node.flags & NodeFlags.Export) { - transformFlags |= TransformFlags.ThisNodeIsES6Export; - } - break; - - case SyntaxKind.ForOfStatement: - transformFlags |= TransformFlags.ThisNodeIsES6ForOfStatement; - break; - - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.ReturnStatement: - if (node.parserContextFlags & ParserContextFlags.Yield) { - transformFlags |= TransformFlags.ThisNodeIsCompletionStatementInGenerator; - } - break; - - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - transformFlags |= TransformFlags.ThisNodeIsES6BindingPattern; - break; - - case SyntaxKind.VariableDeclarationList: - if (node.parserContextFlags & ParserContextFlags.Yield) { - transformFlags |= TransformFlags.ThisNodeIsHoistedDeclarationInGenerator; - } - if (node.flags & (NodeFlags.Let | NodeFlags.Const)) { - transformFlags |= TransformFlags.ThisNodeIsES6LetOrConst; - } - break; - - case SyntaxKind.VariableStatement: - if (node.flags & NodeFlags.Export) { - transformFlags |= TransformFlags.ThisNodeIsES6Export; - } - break; - - case SyntaxKind.Decorator: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptDecorator; - break; - - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - transformFlags |= TransformFlags.ThisNodeIsES6Class; - if (transformFlags & TransformFlags.ContainsTypeScriptClassSyntaxExtension) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassWithSyntaxExtensions; - } - break; - - case SyntaxKind.PropertyDeclaration: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptPropertyDeclaration; - if (node.flags & NodeFlags.Static && (node).initializer) { - transformFlags |= TransformFlags.ContainsTypeScriptGeneratedStatements; - } - - break; - - case SyntaxKind.Constructor: - if (!(node).body) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptOverload; - } - break; - - case SyntaxKind.MethodDeclaration: - if (!(node).body) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptOverload; - } - - transformFlags |= TransformFlags.ThisNodeIsES6MethodDeclaration; - if ((node).asteriskToken) { - transformFlags |= TransformFlags.ThisNodeIsES6Generator; - } - - break; - - case SyntaxKind.EnumDeclaration: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptEnumDeclaration; - break; - - case SyntaxKind.ImportEqualsDeclaration: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptImportEqualsDeclaration; - break; - - case SyntaxKind.ImportDeclaration: - transformFlags |= TransformFlags.ThisNodeIsES6ImportDeclaration; - break; - - case SyntaxKind.ExportAssignment: - transformFlags |= TransformFlags.ThisNodeIsTypeScriptExportAssignmentDeclaration; - break; - - case SyntaxKind.ExportDeclaration: - transformFlags |= TransformFlags.ThisNodeIsES6ExportDeclaration; - break; - } - - node.transformFlags = transformFlags; - - // Exclude flags that should not escape the lexical environment. - if (isArrowFunction(node)) { - transformFlags &= ~TransformFlags.ArrowFunctionScopeExcludes; - } - else if (isFunctionLike(node)) { - transformFlags &= ~TransformFlags.FunctionScopeExcludes; - } - else if (isClassLike(node)) { - transformFlags &= ~TransformFlags.ClassScopeExcludes; - } - else if (nodeStartsNewLexicalEnvironment(node)) { - transformFlags &= ~TransformFlags.ModuleScopeExcludes; - } - } - } } \ No newline at end of file diff --git a/src/compiler/transforms/chain.ts b/src/compiler/transforms/chain.ts index 44a7ac4a03d..b398211f985 100644 --- a/src/compiler/transforms/chain.ts +++ b/src/compiler/transforms/chain.ts @@ -2,6 +2,7 @@ /// /// /// +/*@internal*/ namespace ts.transform { export type TransformationChain = (context: VisitorContext, statements: NodeArray) => NodeArray; @@ -23,26 +24,39 @@ namespace ts.transform { } } + function runTransformation(chain: TransformationChain, context: VisitorContext, statements: NodeArray) { + context.pushLexicalEnvironment(); + + let transformed = chain(context, statements); + if (context.hasHoistedDeclarations()) { + transformed = factory.cloneNodeArray(transformed); + context.writeHoistedDeclarations(transformed); + } + + context.popLexicalEnvironment(); + return transformed; + } + function createUnaryTransformationChain(only: TransformationChain) { return function (context: VisitorContext, statements: NodeArray) { - if (only) statements = only(context, statements); + if (only) statements = runTransformation(only, context, statements); return statements; }; } function createBinaryTransformationChain(first: TransformationChain, second: TransformationChain) { return function (context: VisitorContext, statements: NodeArray) { - if (first) statements = first(context, statements); - if (second) statements = second(context, statements); + if (first) statements = runTransformation(first, context, statements); + if (second) statements = runTransformation(second, context, statements); return statements; }; } function createTrinaryTransformationChain(first: TransformationChain, second: TransformationChain, third: TransformationChain) { return function (context: VisitorContext, statements: NodeArray) { - if (first) statements = first(context, statements); - if (second) statements = second(context, statements); - if (third) statements = third(context, statements); + if (first) statements = runTransformation(first, context, statements); + if (second) statements = runTransformation(second, context, statements); + if (third) statements = runTransformation(third, context, statements); return statements; }; } diff --git a/src/compiler/transforms/es5.ts b/src/compiler/transforms/es5.ts index 82f755afdbd..eb6d1c46d88 100644 --- a/src/compiler/transforms/es5.ts +++ b/src/compiler/transforms/es5.ts @@ -1,438 +1,593 @@ /// +/*@internal*/ namespace ts.transform { export function toES5(context: VisitorContext, statements: NodeArray) { - return statements; + return visitNodes(context, statements, transformNode); + } + + /** + * Transforms a node from ES6 to ES5 if it requires any transformations. + * @param context Context information for the transform. + * @param node The node to transform. + * @remarks + * This function is intentionally kept small to keep its overhead low. + * + * If the node needs direct transformation, it will be passed on to the + * `transformNodeWorker` function. + * + * If any part of its subtree needs transformation, the node will be + * passed to the fallback `accept` function which will ensure any changes + * to the subtree will generate new nodes. + * + * If no part of this node or its subtree requires transformation, the node + * is returned, unchanged. + */ + function transformNode(context: VisitorContext, node: Node, write: (node: Node) => void): void { + if (!node) { + return; + } + + // Debug.assert( + // !needsTransform(node, TransformFlags.ThisNodeNeedsTransformToES6), + // "Cannot transform node with post-ES6 syntax."); + + if (needsTransform(node, TransformFlags.ThisNodeNeedsTransformToES5)) { + return transformNodeWorker(context, node, write); + } + else if (node.flags & NodeFlags.GeneratedSuper && isExpressionStatement(node)) { + return transformInitialSuperCall(context, node, write); + } + else if (needsTransform(node, TransformFlags.SubtreeNeedsTransformToES5)) { + return accept(context, node, transformNode, write); + } + + return write(node); } - // export class ES6ToES5Transformer extends Transformer { - // private builder: StatementBuilder; - // private restIndex: number; - // private containingFunction: FunctionLikeDeclaration; - - // // emitter.ts:4354 - // private transformClassExpression(node: ClassExpression) { - // return this.transformClassLikeDeclaration(node); - // } - - // // emitter.ts:4358 - // private transformClassDeclaration(node: ClassDeclaration) { - // // TODO(rbuckton): SystemJS hoisting - // // source file level classes in system modules are hoisted so 'var's for them are already defined - // // if (!shouldHoistDeclarationInSystemJsModule(node)) { - // // } - - // // var = (function (){ ... })(); - // return factory.createVariableStatement2( - // this.getDeclarationName(node), - // this.transformClassLikeDeclaration(node) - // ); - // } - - // // emitter.ts:4548 - // private transformClassLikeDeclaration(node: ClassLikeDeclaration) { - // let saveBuilder = this.builder; - // this.builder = new StatementBuilder(this.resolver); - - // let baseTypeNode = getClassExtendsHeritageClauseElement(node); - // if (baseTypeNode) { - // this.builder.emitStatement( - // factory.createExpressionStatement( - // factory.createCallExpression2( - // factory.createIdentifier("__extends"), - // [ - // this.getDeclarationName(node), - // factory.createIdentifier("_super") - // ] - // ) - // ) - // ); - // } - - // this.emitConstructor(node, baseTypeNode); - // this.emitMemberFunctions(node); - // this.emitPropertyDeclarations(node, this.getInitializedProperties(node, /*isStatic*/ true)); - // this.builder.emitReturn(this.getDeclarationName(node)); - - // let parameters = baseTypeNode - // ? [factory.createParameter2(factory.createIdentifier("_super"))] - // : []; - - // let _arguments = baseTypeNode - // ? [baseTypeNode.expression] - // : []; - - // let transformed = factory.createInlineFunctionExpressionEvaluation( - // parameters, - // this.builder.readStatements(), - // _arguments - // ); - - // this.builder = saveBuilder; - // return transformed; - // } - - // // emitter.ts:4244 (emitConstructorWorker) - // private emitConstructor(node: ClassLikeDeclaration, baseTypeElement: ExpressionWithTypeArguments): void { - // let saveBuilder = this.builder; - // this.builder = new StatementBuilder(this.resolver); - - // // Check if we have property assignment inside class declaration. - // // If there is 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 = false; - - // for (let member of node.members) { - // // TODO: Emit the constructor overload pinned comments: - // // if (member.kind === SyntaxKind.Constructor && !(member).body) { - // // emitOnlyPinnedOrTripleSlashComments(member); - // // } - // if (isPropertyDeclaration(member) && member.initializer) { - // hasInstancePropertyWithInitializer = true; - // } - // } - - // let ctor = getFirstConstructorWithBody(node); - - // // TODO(rbuckton): Emit comments, source map - // // if (ctor) { - // // emitLeadingComments(ctor); - // // } - // // emitStart(ctor || node); - // // scopeEmitStart(node, "constructor"); - // // if (ctor) { - // // emitDetachedComments(ctor.body.statements); - // // } - - // this.emitCaptureThisForNodeIfNecessary(node); - - // let superCall: ExpressionStatement; - // let parameters: ParameterDeclaration[]; - // if (ctor) { - // parameters = this.transformSignatureParameters(ctor); - // if (baseTypeElement) { - // superCall = this.findInitialSuperCall(ctor); - // if (superCall) { - // this.builder.emitStatement(superCall); - // } - // } - // this.emitParameterPropertyAssignments(ctor); - // } - // else if (baseTypeElement) { - // // _super.apply(this, arguments); - // this.builder.emitStatement( - // factory.createExpressionStatement( - // factory.createCallExpression2( - // factory.createPropertyAccessExpression2( - // factory.createIdentifier("_super"), - // factory.createIdentifier("apply") - // ), - // [ - // factory.createThisKeyword(), - // factory.createIdentifier("arguments") - // ] - // ) - // ), - // /*location*/ baseTypeElement - // ); - // } - - // this.emitPropertyDeclarations(node, this.getInitializedProperties(node, /*static*/ false)); - - // if (ctor) { - // this.builder.emitStatements( - // visitNodes(ctor.body.statements, this, /*cache*/ undefined, /*removeMissingNodes*/ true) - // ); - // } - - // this.builder.emitStatement( - // factory.createFunctionDeclaration3( - // this.getDeclarationName(node), - // parameters, - // this.builder.readStatements() - // ) - // ); - - // this.builder = saveBuilder; - // } - - // // emitter.ts:4026 - // private findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement { - // if (ctor.body) { - // let statement = (ctor.body).statements[0]; - // if (statement && statement.kind === SyntaxKind.ExpressionStatement) { - // let expr = (statement).expression; - // if (expr && expr.kind === SyntaxKind.CallExpression) { - // let func = (expr).expression; - // if (func && func.kind === SyntaxKind.SuperKeyword) { - // return statement; - // } - // } - // } - // } - // } - - // // emitter.ts:4041 - // private emitParameterPropertyAssignments(node: ConstructorDeclaration) { - // for (let parameter of node.parameters) { - // if (parameter.flags & NodeFlags.AccessibilityModifier) { - // // this. = ; - // this.builder.emitAssignment( - // /*left*/ factory.setTextRange( - // factory.createPropertyAccessExpression2( - // factory.createThisKeyword(), - // factory.cloneNode(parameter.name) - // ), - // parameter.name - // ), - // /*right*/ parameter.name, - // /*location*/ parameter - // ); - // } - // } - // } - - // // emitter.ts:3709 - // private emitCaptureThisForNodeIfNecessary(node: Node) { - // // var _this = this; - // if (needsTransform(node, TransformFlags.SubtreeCapturesLexicalThis)) { - // this.builder.emitStatement( - // factory.createVariableStatement2( - // factory.createIdentifier("_this"), - // factory.createThisKeyword())); - // } - // } - - // // emitter.ts:4085 - // private emitPropertyDeclarations(node: ClassLikeDeclaration, properties: PropertyDeclaration[]) { - // for (let property of properties) { - // this.emitPropertyDeclaration(node, property); - // } - // } - - // // emitter.ts:4091 - // private emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) { - // let target = property.flags & NodeFlags.Static - // ? this.getDeclarationName(node) - // : factory.createThisKeyword(); - // this.builder.emitAssignment( - // /*left*/ factory.setTextRange( - // factory.createMemberAccessForPropertyName(target, property.name), - // property.name - // ), - // /*right*/ visit(property.initializer, this), - // /*location*/ property - // ); - // } - - // // emitter.ts:3718 - // private transformSignatureParameters(node: FunctionLikeDeclaration) { - // let saveRestIndex = this.restIndex; - // let saveContainingFunction = this.containingFunction; - // this.restIndex = hasRestParameter(node) ? node.parameters.length - 1 : undefined; - // this.containingFunction = node; - - // let parameters = visitNodes(node.parameters, this, /*cache*/ undefined, /*removeMissingNodes*/ true); - - // this.restIndex = saveRestIndex; - // this.containingFunction = saveContainingFunction; - // return parameters; - // } - - // // emitter.ts:3542 (emitDefaultValueAssignments) - // // emitter.ts:3594 (emitRestParameter) - // private transformParameterDeclaration(parameter: ParameterDeclaration) { - // let { name: paramName, initializer, dotDotDotToken } = parameter; - // if (isBindingPattern(paramName)) { - // let tempParamName = this.builder.createUniqueIdentifier(); - // let tempParameter = factory.createParameter2(tempParamName); + /** + * Transforms a node from ES6 to ES5. + * @param context Context information for the transform. + * @param node The node to transform. + */ + function transformNodeWorker(context: VisitorContext, node: Node, write: (node: Node) => void): void { + switch (node.kind) { + case SyntaxKind.ClassDeclaration: + return transformClassDeclaration(context, node, write); - // // A rest parameter cannot have a binding pattern or an initializer, - // // so let's just ignore it. - // if (dotDotDotToken) { - // return tempParameter; - // } + case SyntaxKind.ClassExpression: + return transformClassExpression(context, node, write); - // // In cases where a binding pattern is simply '[]' or '{}', - // // we usually don't want to emit a var declaration; however, in the presence - // // of an initializer, we must emit that expression to preserve side effects. - // let hasBindingElements = paramName.elements.length > 0; - // if (hasBindingElements) { - // // TODO(rbuckton): binding patterns - // } - // else { - // this.builder.emitStatement( - // factory.createVariableStatement2( - // tempParamName, - // visit(initializer, this) - // ) - // ); - // } + case SyntaxKind.Parameter: + return transformParameter(context, node, write); - // return tempParameter; - // } - // else { - // if (initializer) { - // // A rest parameter cannot have a binding pattern or an initializer, - // // so let's just ignore it. - // if (dotDotDotToken) { - // return undefined; - // } - - // // if ( === void 0) { = ; } - // this.builder.emitStatement( - // factory.createIfStatement( - // /*condition*/ factory.createBinaryExpression2( - // factory.cloneNode(paramName), - // SyntaxKind.EqualsEqualsEqualsToken, - // factory.createVoidZeroExpression() - // ), - // /*thenStatement*/ factory.createBlock([ - // factory.createExpressionStatement( - // factory.createBinaryExpression2( - // factory.cloneNode(paramName), - // SyntaxKind.EqualsToken, - // factory.cloneNode(visit(initializer, this)) - // ) - // ) - // ]) - // ) - // ); - // } - // else if (dotDotDotToken) { - // let tempName = factory.createIdentifier(this.resolver.makeTempVariableName(/*loopVariable*/ true)); - - // // var = []; - // this.builder.emitStatement( - // factory.createVariableStatement2( - // this.getDeclarationName(parameter), - // factory.createArrayLiteralExpression([]) - // ) - // ); - - // // for (var = ; < arguments.length; ++) - // this.builder.emitStatement( - // factory.createForStatement( - // /*initializer*/ factory.createVariableDeclarationList([ - // factory.createVariableDeclaration2( - // tempName, - // factory.createNumericLiteral2(this.restIndex) - // ) - // ]), - // /*condition*/ factory.createBinaryExpression2( - // tempName, - // SyntaxKind.LessThanToken, - // factory.createPropertyAccessExpression2( - // factory.createIdentifier("arguments"), - // factory.createIdentifier("length") - // ) - // ), - // /*incrementer*/ factory.createPostfixUnaryExpression( - // tempName, - // SyntaxKind.PlusPlusToken - // ), - // /*statement*/ factory.createBlock([ - // // [ - ] = arguments[]; - // factory.createExpressionStatement( - // factory.createBinaryExpression2( - // factory.createElementAccessExpression2( - // this.getDeclarationName(parameter), - // factory.createBinaryExpression2( - // tempName, - // SyntaxKind.MinusToken, - // factory.createNumericLiteral2(this.restIndex) - // ) - // ), - // SyntaxKind.EqualsToken, - // factory.createElementAccessExpression2( - // factory.createIdentifier("arguments"), - // tempName - // ) - // ) - // ) - // ]) - // ) - // ); - - // return undefined; - // } - // } - - // return parameter; - // } + case SyntaxKind.FunctionDeclaration: + return transformFunctionDeclaration(context, node, write); - // // emitter.ts:4119 - // private emitMemberFunctions(node: ClassLikeDeclaration): void { - // for (let member of node.members) { - // if (isSemicolonClassElement(member)) { - // this.builder.emitStatement(factory.createEmptyStatement()); - // } - // else if (isMethodDeclaration(member)) { - // if (!member.body) { - // // TODO(rbuckton): emit pinned or triple slash comments - // continue; - // } - - // // TODO(rbuckton): emit leading comments - // this.builder.emitAssignment( - // /*left*/ factory.setTextRange( - // factory.createMemberAccessForPropertyName( - // this.createClassMemberPrefix(node, member), - // member.name - // ), - // member.name - // ), - // /*right*/ this.transformMethodDeclaration(member), - // /*location*/ member - // ); - // } - // else if (isGetAccessor(member) || isSetAccessor(member)) { - // let accessors = getAllAccessorDeclarations(node.members, member); - // if (member === accessors.firstAccessor) { - // this.emitAccessors(node, accessors); - // } - // } - // } - // } - - // private transformMethodDeclaration(method: MethodDeclaration): FunctionExpression { - // return; - // } - - // private emitAccessors(node: ClassLikeDeclaration, accessors: AllAccessorDeclarations) { - - // } - - // // emitter.ts:4074 - // private getInitializedProperties(node: ClassLikeDeclaration, isStatic: boolean): PropertyDeclaration[] { - // let properties: PropertyDeclaration[] = []; - // for (let member of node.members) { - // if (member.kind === SyntaxKind.PropertyDeclaration && isStatic === ((member.flags & NodeFlags.Static) !== 0) && (member).initializer) { - // properties.push(member); - // } - // } - - // return properties; - // } - - // // emitter.ts:4623 - // private createClassMemberPrefix(node: ClassLikeDeclaration, member: Node) { - // let name = this.getDeclarationName(node); - // return member.flags & NodeFlags.Static - // ? name - // : factory.createPropertyAccessExpression2(name, factory.createIdentifier("prototype")); - // } + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + return transformFunctionExpression(context, node, write); + + case SyntaxKind.BindingElement: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ForOfStatement: + case SyntaxKind.SuperKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.YieldExpression: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.VariableDeclarationList: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BinaryExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TemplateExpression: + // TODO (rbuckton): ES6 syntax we're not yet transforming and are leaving for the emitter to handle. + + default: + return accept(context, node, transformNode, write); + } + } + + function transformClassDeclaration(context: VisitorContext, node: ClassDeclaration, write: (node: Statement) => void) { + let name = context.getDeclarationName(node); + let classInitExpr = transformClassLikeDeclaration(context, node, name); + let baseTypeNode = getClassExtendsHeritageClauseElement(node); + let varDecl = factory.createVariableDeclaration2(name, classInitExpr); + let varDecls = factory.createVariableDeclarationList([varDecl]); + let varStmt = factory.createVariableStatement2(varDecls, /*location*/ node); + return write(varStmt); + // return tag_statement` + // var ${name} = (function (${baseTypeNode && tag_id`_super`}) { + // ${baseTypeNode && tag_statement`__extends(${name}, _super);`} + // ${transformConstructor(context, node, baseTypeNode)} + // ${transformMemberFunctions(context, node)} + // return ${name}; + // })(${baseTypeNode && tag_id`_super`}); + // `; + } + + function transformClassExpression(context: VisitorContext, node: ClassExpression, write: (node: LeftHandSideExpression) => void) { + let name = context.getDeclarationName(node); + return write(transformClassLikeDeclaration(context, node, name)); + // let baseTypeNode = getClassExtendsHeritageClauseElement(node); + // return tag_lhs_expression` + // (function (${baseTypeNode && tag_id`_super`}) { + // ${baseTypeNode && tag_statement`__extends(${name}, _super);`} + // ${transformConstructor(context, node, baseTypeNode)} + // ${transformMemberFunctions(context, node)} + // return ${name}; + // })(${baseTypeNode && tag_id`_super`}); + // `; + } - // // emitter.ts:3649 - // private getDeclarationName(node: Declaration) { - // let name = node.name; - // if (name && !nodeIsSynthesized(name)) { - // return factory.cloneNode(name); - // } - // else { - // return factory.createIdentifier( - // this.resolver.getGeneratedNameForNode(node) - // ); - // } - // } - // } + function transformClassLikeDeclaration(context: VisitorContext, node: ClassLikeDeclaration, name: Identifier): LeftHandSideExpression { + let baseTypeNode = getClassExtendsHeritageClauseElement(node); + let superExpr = baseTypeNode ? visitNode(context, baseTypeNode.expression, transformNode) : undefined; + let superName = baseTypeNode ? factory.createIdentifier("_super") : undefined; + let superParam = baseTypeNode ? factory.createParameter2(superName) : undefined; + let classBody = factory.createBlock([]); + if (baseTypeNode) { + let extendsExpr = factory.createExtendsHelperCall(name); + let extendsStmt = factory.createExpressionStatement(extendsExpr); + classBody.statements.push(extendsStmt); + } + + transformConstructor(context, node, name, baseTypeNode, classBody.statements); + transformMemberFunctions(context, node, classBody.statements); + + let returnStmt = factory.createReturnStatement(name); + classBody.statements.push(returnStmt); + + let classDecl = factory.createFunctionExpression2(/*name*/ undefined, baseTypeNode ? [superParam] : [], classBody); + let parenExpr = factory.createParenthesizedExpression(classDecl); + let callExpr = factory.createCallExpression2(parenExpr, baseTypeNode ? [superExpr] : undefined); + return callExpr; + } + + function transformConstructor(context: VisitorContext, node: ClassLikeDeclaration, name: Identifier, baseTypeNode: ExpressionWithTypeArguments, classStatements: Statement[]) { + context.pushLexicalEnvironment(); + + let constructor = getFirstConstructorWithBody(node); + let parameters: ParameterDeclaration[] = constructor ? visitNodes(context, constructor.parameters, transformNode) : []; + let body = factory.createBlock([]); + + if (constructor) { + transformCaptureThisForNode(context, constructor, body.statements); + transformDefaultValueAssignments(context, constructor, body.statements); + transformRestParameter(context, constructor, body.statements); + + let statements = visitNodes(context, constructor.body.statements, transformNode); + body.statements.push(...statements); + } + else if (baseTypeNode) { + let superCall = createDefaultSuperCall(); + body.statements.push(superCall); + } + + context.writeHoistedDeclarations(body.statements); + context.popLexicalEnvironment(); + + let constructorFunc = factory.createFunctionDeclaration2(name, parameters, body); + classStatements.push(constructorFunc); + // return tag_statement` + // function ${name}(${transformSignatureParameters(context, constructor)}) { + // ${transformCaptureThisForNode(context, constructor)} + // ${transformDefaultValueAssignments(context, constructor)} + // ${transformRestParameter(context, constructor)} + // ${visitNodeArrayOfStatement(context, constructor && constructor.body.statements, transformNode)} + // } + // `; + } + + function transformParameter(context: VisitorContext, node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) { + if (isBindingPattern(node.name)) { + write(factory.createParameter2( + context.getGeneratedNameForNode(node), + /*initializer*/ undefined, + /*location*/ node + )); + } + else if (node.initializer) { + write(factory.createParameter2( + node.name, + /*initializer*/ undefined, + /*location*/ node + )); + } + else if (!node.dotDotDotToken) { + // rest parameters are elided, other parameters are included. + write(node); + } + } + + function transformDefaultValueAssignments(context: VisitorContext, node: FunctionLikeDeclaration, statements: Statement[]) { + if (!needsTransform(node, TransformFlags.SubtreeContainsParameterInitializer | TransformFlags.SubtreeContainsParameterBindingPattern)) { + return + } + + for (let parameter of node.parameters) { + let { name, initializer, dotDotDotToken } = parameter; + + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. + if (dotDotDotToken) { + continue; + } + + if (isBindingPattern(name)) { + transformDefaultValueAssignmentForBindingPattern(context, parameter, name, initializer, statements); + } + else if (initializer) { + transformDefaultValueAssignmentForInitializer(context, parameter, name, initializer, statements); + } + } + } + + function transformDefaultValueAssignmentForBindingPattern(context: VisitorContext, parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression, statements: Statement[]): void { + let tempName = context.getGeneratedNameForNode(parameter); + + // In cases where a binding pattern is simply '[]' or '{}', + // we usually don't want to emit a var declaration; however, in the presence + // of an initializer, we must emit that expression to preserve side effects. + let hasBindingElements = name.elements.length > 0; + if (hasBindingElements) { + let varDecls = factory.createVariableDeclarationList([]); + transformBindingElement(context, parameter, tempName, varDecls.declarations, /*assignments*/ undefined); + + let varStmt = factory.createVariableStatement2(varDecls); + factory.startOnNewLine(varStmt); + statements.push(varStmt); + } + else if (initializer) { + let initExpr = visitNode(context, initializer, transformNode); + let assignExpr = factory.createAssignmentExpression(tempName, initExpr); + let assignStmt = factory.createExpressionStatement(assignExpr); + factory.startOnNewLine(assignStmt); + statements.push(assignStmt); + // return tag_statements` + // ${tempName} = ${visit(context, initializer, transformNode)}; + // `; + } + } + + function transformBindingElement(context: VisitorContext, target: BindingElement, value: Expression, declarations: VariableDeclaration[], assignments: Expression[]): void { + if (target.initializer) { + // Combine value and initializer + let initializer = visitNode(context, target.initializer, transformNode); + value = value ? createDefaultValueCheck(context, value, initializer, declarations, assignments) : initializer; + } + else if (!value) { + // Use 'void 0' in absence of value and initializer + value = factory.createVoidZeroExpression(); + } + + let name = target.name; + if (isBindingPattern(name)) { + let elements = name.elements; + if (elements.length !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + value = ensureIdentifier(context, value, declarations, assignments); + } + for (let i = 0; i < elements.length; i++) { + let element = elements[i]; + if (name.kind === SyntaxKind.ObjectBindingPattern) { + // Rewrite element to a declaration with an initializer that fetches property + let propName = element.propertyName || element.name; + transformBindingElement(context, element, factory.createPropertyOrElementAccessExpression(value, propName), declarations, assignments); + } + else if (element.kind !== SyntaxKind.OmittedExpression) { + if (!element.dotDotDotToken) { + // Rewrite element to a declaration that accesses array element at index i + transformBindingElement(context, element, factory.createElementAccessExpression3(value, i), declarations, assignments); + } + else if (i === elements.length - 1) { + transformBindingElement(context, element, factory.createSliceCall(value, i), declarations, assignments); + } + } + } + } + else { + appendAssignment(name, value, declarations, assignments); + } + } + + function appendAssignment(left: Identifier, right: Expression, declarations: VariableDeclaration[], assignments: Expression[]): void { + let varDecl = factory.createVariableDeclaration2(left, assignments ? undefined : right); + declarations.push(varDecl); + + if (assignments) { + let assignExpr = factory.createAssignmentExpression(left, right); + assignments.push(assignExpr); + } + } + + function ensureIdentifier(context: VisitorContext, value: Expression, declarations: VariableDeclaration[], assignments: Expression[]) { + if (isIdentifier(value)) { + return value; + } + else { + let tempVar = context.createTempVariable(/*loopVariable*/ false); + appendAssignment(tempVar, value, declarations, assignments); + return tempVar; + } + } + + function createDefaultValueCheck(context: VisitorContext, value: Expression, defaultValue: Expression, declarations: VariableDeclaration[], assignments: Expression[]) { + value = ensureIdentifier(context, value, declarations, assignments); + let equalityExpr = factory.createStrictEqualityExpression(value, factory.createVoidZeroExpression()); + let conditionalExpr = factory.createConditionalExpression2(equalityExpr, defaultValue, value); + return conditionalExpr; + } + + function transformDefaultValueAssignmentForInitializer(context: VisitorContext, parameter: ParameterDeclaration, name: Identifier, initializer: Expression, statements: Statement[]): void { + name = factory.cloneNode(name); + let equalityExpr = factory.createStrictEqualityExpression(name, factory.createVoidZeroExpression()); + let initExpr = visitNode(context, initializer, transformNode); + let assignExpr = factory.createAssignmentExpression(name, initExpr); + let assignStmt = factory.createExpressionStatement(assignExpr); + let trueStmt = factory.createBlock([assignStmt]); + let ifStmt = factory.createIfStatement(equalityExpr, trueStmt); + factory.startOnNewLine(ifStmt); + statements.push(ifStmt); + // return tag_statement` + // if (${name} === void 0) { + // ${name} = ${visit(context, initializer, transformNode)}; + // } + // `; + } + + function transformRestParameter(context: VisitorContext, node: FunctionLikeDeclaration, statements: Statement[]): void { + if (!needsTransform(node, TransformFlags.SubtreeContainsRestParameter)) { + return; + } + + let restParam = lastOrUndefined(node.parameters); + if (!restParam.dotDotDotToken || restParam.flags & NodeFlags.GeneratedRest) { + return; + } + + let restIndex = node.parameters.length - 1; + let _i = context.createTempVariable(/*loopVariable*/ true); + let name = context.getDeclarationName(restParam); + let arrayExpr = factory.createArrayLiteralExpression([]); + let paramVarDecl = factory.createVariableDeclaration2(name, arrayExpr); + let paramVarDecls = factory.createVariableDeclarationList([paramVarDecl]); + let paramVarStmt = factory.createVariableStatement2(paramVarDecls); + factory.startOnNewLine(paramVarStmt); + statements.push(paramVarStmt); + + let restIndexExpr = factory.createNumericLiteral2(restIndex); + let initializerVarDecl = factory.createVariableDeclaration2(_i, restIndexExpr); + let initializerVarDecls = factory.createVariableDeclarationList([initializerVarDecl]); + let argumentsName = factory.createIdentifier("arguments"); + let lengthName = factory.createIdentifier("length"); + let argumentsLengthExpr = factory.createPropertyAccessExpression2(argumentsName, lengthName); + let conditionExpr = factory.createBinaryExpression2(_i, SyntaxKind.LessThanToken, argumentsLengthExpr); + let incrementerExpr = factory.createPostfixUnaryExpression(_i, SyntaxKind.PlusPlusToken); + let arrayOffsetExpr = restIndex === 0 ? _i : factory.createBinaryExpression2(_i, SyntaxKind.MinusToken, restIndexExpr); + let arrayElementExpr = factory.createElementAccessExpression2(name, arrayOffsetExpr); + let argumentsElementExpr = factory.createElementAccessExpression2(argumentsName, _i); + let assignExpr = factory.createAssignmentExpression(arrayElementExpr, argumentsElementExpr); + let assignStmt = factory.createExpressionStatement(assignExpr); + factory.startOnNewLine(assignStmt); + + let forBody = factory.createBlock([assignStmt]); + let forStmt = factory.createForStatement(initializerVarDecls, conditionExpr, incrementerExpr, forBody); + factory.startOnNewLine(forStmt); + statements.push(forStmt); + // return tag_statements` + // var ${name} = []; + // for (var ${_i} = ${restIndex}; ${_i} < arguments.length; ${_i}++) { + // ${name}[${_i}${restIndex ? tag_part` - ${restIndex}` : undefined}] = arguments[${_i}]; + // } + // `; + } + + function transformCaptureThisForNode(context: VisitorContext, node: Node, statements: Statement[]): void { + if (isArrowFunction(node) || !needsTransform(node, TransformFlags.SubtreeCapturesLexicalThis)) { + return; + } + + let thisName = factory.createIdentifier("_this"); + let thisExpr = factory.createThisKeyword(); + let varDecl = factory.createVariableDeclaration2(thisName, thisExpr); + let varDecls = factory.createVariableDeclarationList([varDecl]); + let varStmt = factory.createVariableStatement2(varDecls); + factory.startOnNewLine(varStmt); + statements.push(varStmt); + + // return tag_statement` + // var _this = this; + // `; + } + + function transformMemberFunctions(context: VisitorContext, node: ClassLikeDeclaration, statements: Statement[]): void { + for (let member of node.members) { + if (isSemicolonClassElement(member)) { + transformSemicolonClassElement(context, member, statements); + } + else if (isMethodDeclaration(member)) { + transformMethodDeclaration(context, node, member, statements); + } + else if (isGetAccessor(member) || isSetAccessor(member)) { + let accessors = getAllAccessorDeclarations(node.members, member); + if (member === accessors.firstAccessor) { + transformAccessorDeclaration(context, node, member, accessors, statements); + } + } + } + } + + function transformSemicolonClassElement(context: VisitorContext, member: SemicolonClassElement, statements: Statement[]): void { + let stmt = factory.createEmptyStatement(); + factory.startOnNewLine(stmt); + statements.push(stmt); + } + + function transformMethodDeclaration(context: VisitorContext, node: ClassLikeDeclaration, member: MethodDeclaration, classStatements: Statement[]): void { + let prefix = context.getClassMemberPrefix(node, member); + let propExpr = getMemberAccessForPropertyName(context, node, member); + let funcExpr = transformToFunctionLikeDeclaration(context, member, /*name*/ undefined, /*location*/ undefined, factory.createFunctionExpression2); + let assignExpr = factory.createAssignmentExpression(propExpr, funcExpr); + let assignStmt = factory.createExpressionStatement(assignExpr, /*location*/ member); + factory.startOnNewLine(assignStmt); + classStatements.push(assignStmt); + // return tag_statement` + // ${property} = ${transformToFunctionExpression(context, member)}; + // `; + } + + function transformAccessorDeclaration(context: VisitorContext, node: ClassLikeDeclaration, member: AccessorDeclaration, accessors: AllAccessorDeclarations, classStatements: Statement[]): void { + let prefix = context.getClassMemberPrefix(node, member); + let name = getExpressionForPropertyName(context, member); + let descriptorExpr = factory.createObjectLiteralExpression2(); + if (accessors.getAccessor) { + let funcExpr = transformToFunctionLikeDeclaration(context, accessors.getAccessor, /*name*/ undefined, /*location*/ accessors.getAccessor, factory.createFunctionExpression2); + let getName = factory.createIdentifier("get"); + let getProp = factory.createPropertyAssignment(getName, funcExpr); + factory.startOnNewLine(getProp); + descriptorExpr.properties.push(getProp); + } + if (accessors.setAccessor) { + let funcExpr = transformToFunctionLikeDeclaration(context, accessors.setAccessor, /*name*/ undefined, /*location*/ accessors.setAccessor, factory.createFunctionExpression2); + let setName = factory.createIdentifier("set"); + let setProp = factory.createPropertyAssignment(setName, funcExpr); + factory.startOnNewLine(setProp); + descriptorExpr.properties.push(setProp); + } + + let trueExpr = factory.createTrueKeyword(); + let enumerableName = factory.createIdentifier("enumerable"); + let enumerableProp = factory.createPropertyAssignment(enumerableName, trueExpr) + factory.startOnNewLine(enumerableProp); + descriptorExpr.properties.push(enumerableProp); + + let configurableName = factory.createIdentifier("configurable"); + let configurableProp = factory.createPropertyAssignment(configurableName, trueExpr); + factory.startOnNewLine(configurableProp); + descriptorExpr.properties.push(configurableProp); + + let definePropertyExpr = factory.createDefinePropertyCall(prefix, name, descriptorExpr); + let definePropertyStmt = factory.createExpressionStatement(definePropertyExpr); + classStatements.push(definePropertyStmt); + // return tag_statement` + // Object.defineProperty(${prefix}, ${name}, { + // ${accessors.getAccessor && tag_part`get: ${transformToFunctionExpression(context, accessors.getAccessor)}, `} + // ${accessors.setAccessor && tag_part`set: ${transformToFunctionExpression(context, accessors.setAccessor)}, `} + // enumerable: true, + // configurable: true + // }); + // `; + } + + function transformFunctionExpression(context: VisitorContext, node: FunctionExpression, write: (node: Expression) => void): void { + let func = transformToFunctionLikeDeclaration(context, node, node.name, /*location*/ node, factory.createFunctionExpression2); + write(func); + } + + function transformFunctionDeclaration(context: VisitorContext, node: FunctionDeclaration, write: (node: Statement) => void): void { + let func = transformToFunctionLikeDeclaration(context, node, node.name, /*location*/ node, factory.createFunctionDeclaration2); + write(func); + } + + function transformToFunctionLikeDeclaration(context: VisitorContext, node: FunctionLikeDeclaration, name: Identifier, location: TextRange, + createFunctionLike: (name: DeclarationName, parameters: ParameterDeclaration[], body: Block, location: TextRange) => T): T { + + context.pushLexicalEnvironment(); + + let parameters = visitNodes(context, node.parameters, transformNode); + let newBody = factory.createBlock([]); + + transformCaptureThisForNode(context, node, newBody.statements); + transformDefaultValueAssignments(context, node, newBody.statements); + transformRestParameter(context, node, newBody.statements); + + let originalBody = node.body; + if (isBlock(originalBody)) { + let statements = visitNodes(context, originalBody.statements, transformNode); + newBody.statements.push(...statements); + factory.setTextRange(newBody, originalBody); + } + else { + let expr = visitNode(context, originalBody, transformNode); + if (expr) { + let returnStmt = factory.createReturnStatement(expr); + newBody.statements.push(returnStmt); + if (!context.childNodeStartPositionIsOnSameLine(node, originalBody)) { + factory.startOnNewLine(returnStmt); + } + } + } + + context.writeHoistedDeclarations(newBody.statements); + context.popLexicalEnvironment(); + + let func = createFunctionLike(name, parameters, newBody, location); + return func; + } + + function getExpressionForPropertyName(context: VisitorContext, member: ClassElement): Expression { + let memberName = member.name; + if (isIdentifier(memberName)) { + return factory.createStringLiteral(memberName.text); + } + else if (isComputedPropertyName(memberName)) { + return visitNode(context, memberName.expression, transformNode); + } + else { + return factory.cloneNode(memberName); + } + } + + function getMemberAccessForPropertyName(context: VisitorContext, node: ClassLikeDeclaration, member: ClassElement): LeftHandSideExpression { + let target = context.getClassMemberPrefix(node, member); + let memberName = member.name; + if (isIdentifier(memberName)) { + return factory.createPropertyAccessExpression2(target, factory.cloneNode(memberName)); + } + else if (isComputedPropertyName(memberName)) { + let expression = visitNode(context, memberName.expression, transformNode); + return factory.createElementAccessExpression2(target, expression); + } + else { + return factory.createElementAccessExpression2(target, factory.cloneNode(memberName)); + } + } + + function transformThisKeyword(context: VisitorContext, node: LeftHandSideExpression): LeftHandSideExpression { + let container = getThisContainer(node, /*includeArrowFunctions*/ true, context.getAncestorOrSelfCallback, /*offset*/ 0); + if (isArrowFunction(container)) { + let thisName = factory.createIdentifier("_this"); + return thisName; + // return tag_id`_this`; + } + return node; + } + + function transformInitialSuperCall(context: VisitorContext, node: ExpressionStatement, write: (node: Statement) => void) { + let statement = createDefaultSuperCall(); + return write(statement); + // return tag_statement` + // _super.apply(this, arguments); + // `; + } + + function createDefaultSuperCall() { + let superName = factory.createIdentifier("_super"); + let thisExpr = factory.createThisKeyword(); + let argumentsName = factory.createIdentifier("arguments"); + let applyExpr = factory.createApplyCall(superName, thisExpr, argumentsName); + let statement = factory.createExpressionStatement(applyExpr); + factory.startOnNewLine(statement); + return statement; + } } \ No newline at end of file diff --git a/src/compiler/transforms/es6.ts b/src/compiler/transforms/es6.ts index 34073e3456b..120db7e1a4b 100644 --- a/src/compiler/transforms/es6.ts +++ b/src/compiler/transforms/es6.ts @@ -1,31 +1,78 @@ /// +/*@internal*/ namespace ts.transform { export function toES6(context: VisitorContext, statements: NodeArray) { - return transform.visitNodeArrayOfStatement(context, statements, transformNode); + return transform.visitNodes(context, statements, transformNode); } - function transformNode(context: VisitorContext, node: Node): Node { - if (!node) { - return node; - } - + /** + * Transforms a node from TypeScript to ES6 if it requires any transformations. + * @param context Context information for the transform. + * @param node The node to transform. + * @remarks + * This function is intentionally kept small to keep its overhead low. + * + * If the node needs direct transformation, it will be passed on to the + * `transformNodeWorker` function. + * + * If any part of its subtree needs transformation, the node will be + * passed to the fallback `accept` function which will ensure any changes + * to the subtree will generate new nodes. + * + * If no part of this node or its subtree requires transformation, the node + * is returned, unchanged. + */ + function transformNode(context: VisitorContext, node: T, write: (node: T) => void): void { if (needsTransform(node, TransformFlags.ThisNodeNeedsTransformToES6)) { - return transformNodeWorker(context, node); + transformNodeWorker(context, node, write); } else if (needsTransform(node, TransformFlags.SubtreeNeedsTransformToES6)) { - return accept(context, node, transformNode); + accept(context, node, transformNode, write); + } + else { + write(node); } - - return node; } - function transformNodeWorker(context: VisitorContext, node: Node): Node { - // Elide ambient nodes + function transformModuleElement(context: VisitorContext, node: Node, write: (node: Node) => void): void { + if (node.flags & NodeFlags.Export) { + transformNodeWorker(context, node, write); + } + else { + transformNode(context, node, write); + } + } + + /** + * Transforms a node from TypeScript to ES6. + * @param context Context information for the transform. + * @param node The node to transform. + */ + function transformNodeWorker(context: VisitorContext, node: Node, write?: (node: Node) => void): void { + // TypeScript ambient declarations are elided. if (node.flags & NodeFlags.Ambient) { return undefined; } switch (node.kind) { + // case SyntaxKind.Block: + // case SyntaxKind.ModuleBlock: + // case SyntaxKind.CaseClause: + // case SyntaxKind.DefaultClause: + // // These nodes contain statement lists which may need to be expanded to include multiple statements... + // // See NodeArraywrite in transform.ts for approach + + // case SyntaxKind.DoStatement: + // case SyntaxKind.WhileStatement: + // case SyntaxKind.ForStatement: + // case SyntaxKind.ForInStatement: + // case SyntaxKind.ForOfStatement: + // case SyntaxKind.IfStatement: + // case SyntaxKind.LabeledStatement: + // case SyntaxKind.WithStatement: + // // These nodes contain single statement nodes that may need to be switched to a block if a child node needs multiple statements... + // // See Statementwrite in transform.ts for approach + case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: @@ -33,320 +80,464 @@ namespace ts.transform { case SyntaxKind.AsyncKeyword: case SyntaxKind.ConstKeyword: case SyntaxKind.DeclareKeyword: - // TypeScript accessibility modifiers are elided - return undefined; + // TypeScript accessibility modifiers are elided. + + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + case SyntaxKind.TypeLiteral: + case SyntaxKind.TypePredicate: + case SyntaxKind.TypeParameter: + case SyntaxKind.AnyKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.ConstructorType: + case SyntaxKind.FunctionType: + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeReference: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + // TypeScript type nodes are elided. + + case SyntaxKind.IndexSignature: + // TypeScript index signatures are elided. case SyntaxKind.Decorator: - // TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration - return undefined; + // TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration. case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: // TypeScript type-only declarations are elided - return undefined; - - case SyntaxKind.ClassDeclaration: - // This is a class declaration with TypeScript syntax extensions. - // TypeScript class syntax extensions include: Decorators, Parameter Property Assignments, Property Declarations - return transformClassDeclaration(context, node); - case SyntaxKind.ClassExpression: - // This is a class expression with TypeScript syntax extensions. - return transformClassExpression(context, node); - - case SyntaxKind.HeritageClause: - return transformHeritageClause(context, node); - - case SyntaxKind.ExpressionWithTypeArguments: - return transformExpressionWithTypeArguments(context, node); - - case SyntaxKind.Constructor: - // TypeScript repositions the constructor of a class to the first element - return undefined; - case SyntaxKind.PropertyDeclaration: - // TypeScript property declarations are elided - return undefined; + // TypeScript property declarations are elided. case SyntaxKind.IndexSignature: - // TypeScript index signatures are elided - return undefined; + // TypeScript index signatures are elided. case SyntaxKind.Constructor: // TypeScript constructors are elided. The constructor of a class will be - // reordered to the start of the member list in transformClassDeclaration. - return undefined; + // reordered to the start of the member list in `transformClassDeclaration`. + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + // TypeScript interfaces and type aliases are elided. + + return; + + case SyntaxKind.ClassDeclaration: + // This is a class declaration with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return transformClassDeclaration(context, node, write); + + case SyntaxKind.ClassExpression: + // This is a class expression with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return transformClassExpression(context, node, write); + + case SyntaxKind.HeritageClause: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause + return transformHeritageClause(context, node, write); + + case SyntaxKind.ExpressionWithTypeArguments: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. + return transformExpressionWithTypeArguments(context, node, write); + case SyntaxKind.MethodDeclaration: - // TypeScript method declarations may be 'async', and may have decorators. - return transformMethodDeclaration(context, node); + // TypeScript method declarations may be 'async', and may have decorators, modifiers + // or type annotations. + return transformMethodDeclaration(context, node, write); case SyntaxKind.GetAccessor: - return transformGetAccessor(context, node); + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. + return transformGetAccessor(context, node, write); case SyntaxKind.SetAccessor: - return transformSetAccessor(context, node); + // Set Accessors can have TypeScript modifiers, decorators, and type annotations. + return transformSetAccessor(context, node, write); + + case SyntaxKind.FunctionDeclaration: + // TypeScript function declarations may be 'async' + return transformFunctionDeclaration(context, node, write); + + case SyntaxKind.FunctionExpression: + // TypeScript function expressions may be 'async' + return transformFunctionExpression(context, node, write); + + case SyntaxKind.ArrowFunction: + // TypeScript arrow functions may be 'async' + return transformArrowFunction(context, node, write); + + case SyntaxKind.Parameter: + // This is a parameter declaration with TypeScript syntax extensions. + // + // TypeScript parameter declaration syntax extensions include: + // - decorators + // - accessibility modifiers + // - the question mark (?) token for optional parameters + // - type annotations + return transformParameter(context, node, write); + + case SyntaxKind.TypeAssertionExpression: + // TypeScript type assertions are removed, but their subtrees are preserved. + return write((node).expression); + + case SyntaxKind.AsExpression: + // TypeScript `as` expressions are removed, but their subtrees are preserved. + return write((node).expression); + + case SyntaxKind.EnumDeclaration: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. + return transformEnumDeclaration(context, node, write); + + case SyntaxKind.AwaitExpression: + // TypeScript 'await' expressions must be transformed. + return transformAwaitExpression(context, node, write); + + // case SyntaxKind.VariableStatement: + // // TypeScript namespace exports for variable statements must be transformed. + // return transformVariableStatement(context, node, write); + + case SyntaxKind.ModuleDeclaration: + // TypeScript namespace declarations must be transformed. + return transformModuleDeclaration(context, node, write); + + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportAssignment: + // TODO(rbuckton): TypeScript extensions we're not yet transforming. default: - return transform.accept(context, node, transformNode); + // Fall back to the default visit behavior as some part of this node's + // subtree requires a transformation. + return accept(context, node, transformNode, write); } } - - function transformClassDeclaration(context: VisitorContext, node: ClassDeclaration): ClassDeclaration { - let baseTypeNode = getClassExtendsHeritageClauseElement(node); - let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNodeWorker); - let heritageClauses = visitNodeArrayOfHeritageClause(context, node.heritageClauses, transformNodeWorker); - let ctor = transformConstructor(context, node, baseTypeNode !== undefined); - let members = visitNodeArrayOfClassElement(context, node.members, transformNodeWorker); - if (ctor) { - members = factory.createNodeArray([ctor, ...members]); - } + + /** + * Transforms a TypeScript class declaration with syntax extensions into compatible ES6. + * @param context Context information for the transform. + * @param node The node to transform. + */ + function transformClassDeclaration(context: VisitorContext, node: ClassDeclaration, write: (node: Statement) => void) { + let thisNodeIsNamespaceExport = isNamespaceLevelExport(context, node); + let name = context.getDeclarationName(node); + let heritageClauses = visitNodes(context, node.heritageClauses, transformNode); + let extendsClause = heritageClauses && firstOrUndefined(heritageClauses); + let baseTypeNode = extendsClause && firstOrUndefined(extendsClause.types); + let constructor = transformConstructor(context, node, baseTypeNode); + let members = visitNodes(context, node.members, transformNode); + let classMembers: ClassElement[] = constructor ? [constructor, ...members] : members; - if (node.decorators) { - let newNode = factory.createVariableStatement2( - context.getDeclarationName(node), - factory.createClassExpression2( - node.name ? context.createUniqueIdentifier(node.name.text) : undefined, - heritageClauses ? heritageClauses[0] : undefined, - members - ), - /*location*/ node, - NodeFlags.Let - ); - newNode.original = node; - context.emitStatement(newNode); + if (nodeIsDecorated(node)) { + let classExpr = factory.createClassExpression2(/*name*/ undefined, extendsClause, classMembers); + let varDecl = factory.createVariableDeclaration2(name, classExpr); + let varDeclList = factory.createVariableDeclarationList([varDecl], /*location*/ undefined, NodeFlags.Let); + let exportFlags = isTopLevelNonDefaultExport(context, node) ? NodeFlags.Export : undefined; + let varStmt = factory.createVariableStatement2(varDeclList, /*location*/ node, exportFlags); + varStmt.original = node; + write(varStmt); } else { - let newNode = factory.updateClassDeclaration( - node, - /*decorators*/ undefined, - /*modifiers*/ modifiers, - node.name, - /*typeParameters*/ undefined, - /*heritageClauses*/ heritageClauses, - /*members*/ members - ); + let exportFlags = thisNodeIsNamespaceExport + ? undefined + : node.flags & (NodeFlags.Export | NodeFlags.Default); + let classDecl = factory.createClassDeclaration2(name, extendsClause, classMembers, /*location*/ node, exportFlags); + classDecl.original = node; + write(classDecl); } - let staticPropertyAssignments = getInitializedProperties(node, /*isStatic*/ true); - if (staticPropertyAssignments) { - emitPropertyDeclarations(context, node, staticPropertyAssignments); + transformPropertyDeclarationsToStatements(context, node, getInitializedProperties(node, /*isStatic*/ true), write); + transformDecoratorsOfMembers(context, node, /*isStatic*/ false, write); + transformDecoratorsOfMembers(context, node, /*isStatic*/ true, write); + transformDecoratorsOfConstructor(context, node, write); + + if (thisNodeIsNamespaceExport) { + let namespaceExportExpr = factory.createAssignmentExpression(getModuleMemberName(context, node), name); + let exprStmt = factory.createExpressionStatement(namespaceExportExpr); + write(exprStmt); } - - // Transform any decorators into following statements - emitDecoratorsOfClass(context, node); - return undefined; + else if (isTopLevelDefaultExport(context, node) && nodeIsDecorated(node)) { + let exportDefaultStmt = factory.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, name); + write(exportDefaultStmt); + } + + // let exportPart = thisNodeIsTopLevelExport && (!thisNodeIsDecorated || !thisNodeIsDefaultExport) && tag_part`export`; + // let defaultPart = thisNodeIsTopLevelExport && thisNodeIsDefaultExport && tag_part`default`; + // let extendsPart = baseTypeNode && tag_part`extends ${baseTypeNode}`; + // let namespaceExportPart = !thisNodeIsTopLevelExport && (node.flags & NodeFlags.Export) && tag_part`${getModuleMemberName(context, node)} = ${name}`; + // let exportDefaultPart = thisNodeIsTopLevelExport && (node.flags & NodeFlags.Default) && thisNodeIsDecorated && tag_part`export default ${name}`; + // let statements = tag_statements` + // ${thisNodeIsDecorated + // ? tag_part`${exportPart} let ${name} = class` + // : tag_part`${exportPart} ${defaultPart} class ${name}` + // } ${extendsPart} { + // ${constructor} + // ${members} + // } + // ${transformPropertyDeclarationsToStatements(context, node, getInitializedProperties(node, /*isStatic*/ true)} + // ${transformDecoratorsOfMembers(context, node, /*isStatic*/ false)} + // ${transformDecoratorsOfMembers(context, node, /*isStatic*/ true)} + // ${transformDecoratorsOfConstructor(context, node)} + // ${namespaceExportPart} + // ${exportDefaultPart} + // `; + // statements[0].original = node; } + + function transformClassExpression(context: VisitorContext, node: ClassExpression, write: (node: LeftHandSideExpression) => void) { + let name = context.getDeclarationName(node); + let heritageClauses = visitNodes(context, node.heritageClauses, transformNode); + let extendsClause = heritageClauses ? firstOrUndefined(heritageClauses) : undefined; + let baseTypeNode = extendsClause ? firstOrUndefined(extendsClause.types) : undefined; + let constructor = transformConstructor(context, node, baseTypeNode); + let members = visitNodes(context, node.members, transformNodeWorker); + let classMembers = constructor ? [constructor, ...members] : members; - function transformClassExpression(context: VisitorContext, node: ClassExpression): LeftHandSideExpression { - // TODO(rbuckton): Handle decorators, for now we don't change the class and let the old emitter handle this - if (node.decorators) { - return node; - } - - let baseTypeNode = getClassExtendsHeritageClauseElement(node); - let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNodeWorker); - let heritageClauses = visitNodeArrayOfHeritageClause(context, node.heritageClauses, transformNodeWorker); - let ctor = transformConstructor(context, node, baseTypeNode !== undefined); - let members = visitNodeArrayOfClassElement(context, node.members, transformNodeWorker); - if (ctor) { - members = factory.createNodeArray([ctor, ...members]); - } - - let newNode = factory.updateClassExpression( - node, - /*decorators*/ undefined, - /*modifiers*/ modifiers, - node.name, - /*typeParameters*/ undefined, - /*heritageClauses*/ heritageClauses, - /*members*/ members + let newNode = factory.createClassExpression2( + name, + extendsClause, + classMembers ); let staticPropertyAssignments = getInitializedProperties(node, /*isStatic*/ true); if (staticPropertyAssignments) { - let tempVariable = context.declareLocal(); - return factory.createParenthesizedExpression( - factory.inlineExpressions([ - factory.createAssignmentExpression(tempVariable, newNode), - ...transformPropertyDeclarations(context, node, staticPropertyAssignments), - tempVariable - ]) - ); + let expressions: Expression[] = []; + let tempVar = context.declareLocal(); + let cacheExpr = factory.createAssignmentExpression(tempVar, newNode); + expressions.push(cacheExpr); + transformPropertyDeclarationsToExpressions(context, node, staticPropertyAssignments, expressions); + expressions.push(tempVar); + write(factory.createParenthesizedExpression(factory.inlineExpressions(expressions))); + // return tag_lhs_expression` + // ${tempVariable} = ${newNode}, + // ${factory.inlineExpressions(expressions)}, + // ${tempVariable} + // `; } - - return newNode; + else { + write(newNode); + } + } + + function isTopLevelExport(context: VisitorContext, node: Node) { + return !!(node.flags & NodeFlags.Export) && + context.parentNode.kind === SyntaxKind.SourceFile; } - function transformConstructor(context: VisitorContext, node: ClassLikeDeclaration, hasBaseType: boolean) { + function isTopLevelDefaultExport(context: VisitorContext, node: Node) { + return isTopLevelExport(context, node) && !!(node.flags & NodeFlags.Default); + } + + function isTopLevelNonDefaultExport(context: VisitorContext, node: Node) { + return isTopLevelExport(context, node) && !(node.flags & NodeFlags.Default); + } + + function isNamespaceLevelExport(context: VisitorContext, node: Node) { + return !!(node.flags & NodeFlags.Export) && + context.parentNode.kind !== SyntaxKind.SourceFile; + } + + function getContainingModule(context: VisitorContext): ModuleDeclaration { + return context.findAncestorNode(isModuleDeclaration); + } + + function getContainingModuleName(context: VisitorContext): Identifier { + let container = context.findAncestorNode(isModuleDeclaration); + return container ? context.getGeneratedNameForNode(container) : factory.createIdentifier("exports"); + // return container ? context.getGeneratedNameForNode(container) : tag_id`exports`; + } + + function getModuleMemberName(context: VisitorContext, node: Declaration): Expression { + let name = context.getDeclarationName(node); + Debug.assert(isIdentifier(name)); + + if (context.getCombinedNodeFlags() & NodeFlags.Export) { + let container = getContainingModuleName(context); + let propExpr = factory.createPropertyAccessExpression2(container, name); + return propExpr; + // return tag_expression` + // ${container}.${name} + // `; + } + return name; + } + + function transformConstructor(context: VisitorContext, node: ClassLikeDeclaration, baseTypeNode: ExpressionWithTypeArguments) { // Check if we have a 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 ctor = getFirstConstructorWithBody(node); - let parameterPropertyAssignments = ctor ? getParametersWithPropertyAssignments(ctor) : undefined; + let constructor = getFirstConstructorWithBody(node); + let parameterPropertyAssignments = constructor ? getParametersWithPropertyAssignments(constructor) : undefined; let instancePropertyAssignments = getInitializedProperties(node, /*isStatic*/ false); - let leadingCommentRanges: CommentRange[]; - let trailingCommentRanges: CommentRange[]; - for (let member of node.members) { - if (isConstructor(member) && !member.body) { - let leadingCommentRangesOfMember = context.getLeadingCommentRanges(member, /*onlyPinnedOrTripleSlashComments*/ true); - leadingCommentRanges = concatenate(leadingCommentRanges, leadingCommentRangesOfMember); - } - } + // let leadingCommentRanges: CommentRange[]; + // let trailingCommentRanges: CommentRange[]; + // for (let member of node.members) { + // if (isConstructor(member) && !member.body) { + // let leadingCommentRangesOfMember = context.getLeadingCommentRanges(member, /*onlyPinnedOrTripleSlashComments*/ true); + // leadingCommentRanges = concatenate(leadingCommentRanges, leadingCommentRangesOfMember); + // } + // } // For target ES6 and above, if there is no property assignment // do not emit constructor in class declaration. if (!parameterPropertyAssignments && !instancePropertyAssignments) { - if (leadingCommentRanges) { - leadingCommentRanges = concatenate(leadingCommentRanges, context.getLeadingCommentRanges(ctor)); - ctor = factory.cloneNode(ctor); - factory.attachCommentRanges(ctor, leadingCommentRanges, trailingCommentRanges); - } + // if (leadingCommentRanges) { + // leadingCommentRanges = concatenate(leadingCommentRanges, context.getLeadingCommentRanges(ctor)); + // ctor = factory.cloneNode(ctor); + // factory.attachCommentRanges(ctor, leadingCommentRanges, trailingCommentRanges); + // } - return ctor; + return constructor; } - context.pushStatements(); let parameters = - ctor ? visitNodeArrayOfParameter(context, ctor.parameters, transformNode) : - hasBaseType ? [factory.createRestParameter(factory.createIdentifier("args"))] : + constructor ? visitNodes(context, constructor.parameters, transformNode) : + baseTypeNode ? [factory.createRestParameter(factory.createIdentifier("args"), /*location*/ undefined, NodeFlags.GeneratedRest)] : []; + // let parameters = + // constructor ? transformSignatureParameters(context, constructor.parameters) : + // hasBaseType ? [factory.createRestParameter(tag_id`args`, /*location*/ undefined, NodeFlags.GeneratedRest)] : + // []; + + let statements: Statement[] = []; let superCall: ExpressionStatement; - if (ctor) { - leadingCommentRanges = concatenate( - leadingCommentRanges, - context.getLeadingCommentRanges(ctor) - ); - trailingCommentRanges = context.getTrailingCommentRanges(ctor); + if (constructor) { + // leadingCommentRanges = concatenate( + // leadingCommentRanges, + // context.getLeadingCommentRanges(ctor) + // ); + // trailingCommentRanges = context.getTrailingCommentRanges(ctor); - if (hasBaseType) { - superCall = findInitialSuperCall(ctor); + if (baseTypeNode) { + superCall = findInitialSuperCall(constructor); if (superCall) { - context.emitStatement(superCall); + statements.push(superCall); } } if (parameterPropertyAssignments) { for (let parameter of parameterPropertyAssignments) { - context.emitAssignmentStatement( - factory.createPropertyAccessExpression2( - factory.createThisKeyword(), - factory.cloneNode(parameter.name) - ), - factory.cloneNode(parameter.name) - ); + let name = factory.cloneNode(parameter.name); + let thisExpr = factory.createThisKeyword(); + let propExpr = factory.createPropertyAccessExpression2(thisExpr, name); + let assignExpr = factory.createAssignmentExpression(propExpr, name); + let assignStmt = factory.createExpressionStatement(assignExpr); + factory.startOnNewLine(assignStmt); + statements.push(assignStmt); + // statements.push(tag_statement` + // this.${name} = ${name}; + // `); } } } - else if (hasBaseType) { - context.emitExpressionStatement( - factory.createCallExpression2( - factory.createNode(SyntaxKind.SuperKeyword), - [ - factory.createSpreadElementExpression( - factory.createIdentifier("args") - ) - ] - ) - ); + else if (baseTypeNode) { + let superExpr = factory.createSuperKeyword(); + let argsName = factory.createIdentifier("args"); + let spreadExpr = factory.createSpreadElementExpression(argsName); + let callExpr = factory.createCallExpression2(superExpr, [spreadExpr]); + let callStmt = factory.createExpressionStatement(callExpr, /*location*/ undefined, NodeFlags.GeneratedSuper); + factory.startOnNewLine(callStmt); + // let statement = tag_statement` + // super(...args); + // `; + // statement.flags |= NodeFlags.GeneratedSuper; + statements.push(callStmt); } - if (instancePropertyAssignments) { - emitPropertyDeclarations(context, node, instancePropertyAssignments); - } + transformPropertyDeclarationsToStatements(context, node, instancePropertyAssignments, n => { statements.push(n); }); - if (ctor) { + if (constructor) { let bodyStatements = superCall - ? ctor.body.statements - : ctor.body.statements.slice(1); - context.emitStatements(visitNodes(context, bodyStatements, transformNode, visitStatement)); + ? constructor.body.statements.slice(1) + : constructor.body.statements; + statements.push(...visitNodes(context, bodyStatements, transformNode)); } - let statements = factory.createNodeArray( - context.getStatements(), - /*location*/ ctor ? ctor.body.statements : undefined); - - let body = ctor - ? factory.updateBlock(ctor.body, statements) + let body = constructor + ? factory.updateBlock(constructor.body, statements) : factory.createBlock(statements); - context.popStatements(); - - if (ctor) { - ctor = factory.updateConstructor( - ctor, - /*decorators*/ undefined, - /*modifiers*/ undefined, - parameters, - /*type*/ undefined, - body - ); - } - else { - ctor = factory.createConstructor( - /*decorators*/ undefined, - /*modifiers*/ undefined, - parameters, - /*type*/ undefined, - body - ); - } - - factory.attachCommentRanges(ctor, leadingCommentRanges, trailingCommentRanges); - return ctor; + let newConstructor = factory.createConstructor2(parameters, body, /*location*/ constructor); + // factory.attachCommentRanges(newConstructor, leadingCommentRanges, trailingCommentRanges); + return newConstructor; } - function transformHeritageClause(context: VisitorContext, node: HeritageClause): Node { + function transformHeritageClause(context: VisitorContext, node: HeritageClause, write: (node: HeritageClause) => void) { if (node.token === SyntaxKind.ExtendsKeyword) { - return factory.updateHeritageClause( + write(factory.updateHeritageClause( node, - visitNodeArrayOfExpressionWithTypeArguments(context, node.types, transformNode) - ); + visitNodes(context, node.types, transformNode) + )); } - - return undefined; } - function transformExpressionWithTypeArguments(context: VisitorContext, node: ExpressionWithTypeArguments) { - return factory.updateExpressionWithTypeArguments( + function transformExpressionWithTypeArguments(context: VisitorContext, node: ExpressionWithTypeArguments, write: (node: ExpressionWithTypeArguments) => void) { + write(factory.updateExpressionWithTypeArguments( node, - node.expression, + visitNode(context, node.expression, transformNode), /*typeArguments*/ undefined - ); + )); } - // emitter.ts:4091 - function emitPropertyDeclarations(context: VisitorContext, node: ClassLikeDeclaration, properties: PropertyDeclaration[]): void { + function transformPropertyDeclarationsToStatements(context: VisitorContext, node: ClassLikeDeclaration, properties: PropertyDeclaration[], write: (node: Statement) => void) { + if (!properties) { + return; + } + for (let property of properties) { let propertyAssignment = transformPropertyDeclaration(context, node, property); - let propertyStatement = factory.createExpressionStatement(propertyAssignment); - propertyStatement.original = property; - context.emitStatement(propertyStatement); + let propertyStatement = factory.createExpressionStatement(propertyAssignment, /*location*/ property); + write(propertyStatement); } } - function transformPropertyDeclarations(context: VisitorContext, node: ClassLikeDeclaration, properties: PropertyDeclaration[]): Expression[] { - let expressions: Expression[] = []; + function transformPropertyDeclarationsToExpressions(context: VisitorContext, node: ClassLikeDeclaration, properties: PropertyDeclaration[], expressions: Expression[]) { + if (!properties) { + return; + } + for (let property of properties) { - let propertyAssignment = transformPropertyDeclaration(context, node, property); - propertyAssignment.original = property; + let propertyAssignment = transformPropertyDeclaration(context, node, property, /*location*/ property); expressions.push(propertyAssignment); } - return expressions; } - function transformPropertyDeclaration(context: VisitorContext, node: ClassLikeDeclaration, property: PropertyDeclaration): Expression { + function transformPropertyDeclaration(context: VisitorContext, node: ClassLikeDeclaration, property: PropertyDeclaration, location?: TextRange): Expression { let isStatic = (property.flags & NodeFlags.Static) !== 0; let target = isStatic ? context.getDeclarationName(node) : factory.createThisKeyword(); - let name = transformPropertyName(context, property, /*isPerInstance*/ !isStatic); - return factory.createAssignmentExpression( - factory.createMemberAccessForPropertyName(target, name, /*location*/ property.name), - visitExpression(context, property.initializer, transformNode) - ); + let name = transformPropertyName(context, property); + let left = factory.createMemberAccessForPropertyName(target, name, /*location*/ property.name); + let initializer = visitNode(context, property.initializer, transformNode); + let assignExpr = factory.createAssignmentExpression(left, initializer); + factory.setTextRange(assignExpr, location); + return assignExpr; + // return tag_expression` + // ${left} = ${initializer} + // `; } // emitter.ts:4074 @@ -395,107 +586,461 @@ namespace ts.transform { } } - function transformMethodDeclaration(context: VisitorContext, node: MethodDeclaration) { + function transformMethodDeclaration(context: VisitorContext, node: MethodDeclaration, write: (node: ClassElement) => void) { if (!node.body) { - let missing = factory.createNode(SyntaxKind.MissingDeclaration, /*location*/ node); - missing.original = node; - return missing; + // let missing = factory.createNode(SyntaxKind.MissingDeclaration, /*location*/ node); + // missing.original = node; + // return missing; + return; } - let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode); let name = transformPropertyName(context, node); - let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode); - let body = visitBlock(context, node.body, transformNode); - return factory.updateMethodDeclaration( - node, - /*decorators*/ undefined, - modifiers, + let parameters = visitNodes(context, node.parameters, transformNode); + + let body: Block; + if (isAsyncFunctionLike(node)) { + body = transformAsyncFunctionBody(context, node); + } + else { + body = visitNode(context, node.body, transformNode); + } + + write(factory.createMethodDeclaration2( name, - /*typeParameters*/ undefined, parameters, - /*typeNode*/ undefined, - body - ); + body, + /*location*/ node, + /*flags*/ node.flags & NodeFlags.Static + )); } - function transformGetAccessor(context: VisitorContext, node: GetAccessorDeclaration) { - let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode); + function transformGetAccessor(context: VisitorContext, node: GetAccessorDeclaration, write: (node: ClassElement) => void) { let name = transformPropertyName(context, node); - let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode); - let body = visitBlock(context, node.body, transformNode); - return factory.updateGetAccessor( - node, - /*decorators*/ undefined, - modifiers, + let parameters = visitNodes(context, node.parameters, transformNode); + let body = visitNode(context, node.body, transformNode); + write(factory.createGetAccessor2( name, parameters, - /*typeNode*/ undefined, - body - ); + body, + /*location*/ node, + /*flags*/ node.flags & NodeFlags.Static + )); } - function transformSetAccessor(context: VisitorContext, node: SetAccessorDeclaration) { - let modifiers = visitNodeArrayOfModifier(context, node.modifiers, transformNode); + function transformSetAccessor(context: VisitorContext, node: SetAccessorDeclaration, write: (node: ClassElement) => void) { let name = transformPropertyName(context, node); - let parameters = visitNodeArrayOfParameter(context, node.parameters, transformNode); - let body = visitBlock(context, node.body, transformNode); - return factory.updateSetAccessor( - node, - /*decorators*/ undefined, - modifiers, + let parameters = visitNodes(context, node.parameters, transformNode); + let body = visitNode(context, node.body, transformNode); + write(factory.createSetAccessor2( name, parameters, - /*typeNode*/ undefined, - body - ); + body, + /*location*/ node, + /*flags*/ node.flags & NodeFlags.Static + )); + } + + function transformFunctionDeclaration(context: VisitorContext, node: FunctionDeclaration, write: (node: Statement) => void) { + if (!node.body) { + // Function overloads are elided + return; + } + + let thisNodeIsNamespaceExport = isNamespaceLevelExport(context, node); + let flags = thisNodeIsNamespaceExport + ? undefined + : node.flags & (NodeFlags.Default | NodeFlags.Export); + + let funcDecl = factory.createFunctionDeclaration3( + node.asteriskToken, + node.name, + visitNodes(context, node.parameters, transformNode), + transformFunctionBody(context, node), + /*location*/ node, + flags); + + write(funcDecl); + + if (thisNodeIsNamespaceExport) { + let namespaceExportExpr = factory.createAssignmentExpression(getModuleMemberName(context, node), factory.cloneNode(node.name)); + let exprStmt = factory.createExpressionStatement(namespaceExportExpr); + write(exprStmt); + } + } + + function transformFunctionExpression(context: VisitorContext, node: FunctionExpression, write: (node: FunctionExpression) => void) { + write(factory.createFunctionExpression3( + node.asteriskToken, + node.name, + visitNodes(context, node.parameters, transformNode), + transformFunctionBody(context, node), + /*location*/ node)); + } + + function transformArrowFunction(context: VisitorContext, node: ArrowFunction, write: (node: ArrowFunction) => void) { + write(factory.createArrowFunction( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + visitNodes(context, node.parameters, transformNode), + /*type*/ undefined, + node.equalsGreaterThanToken, + transformFunctionBody(context, node), + /*location*/ node)); + } + + function transformFunctionBody(context: VisitorContext, node: FunctionLikeDeclaration): Block | Expression { + if (isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(context, node); + } + else { + return visitNode(context, node.body, transformNode); + } + } + + function transformAsyncFunctionBody(context: VisitorContext, node: FunctionLikeDeclaration): Block | Expression { + let promiseConstructor = getEntityNameFromTypeNode(node.type); + let hasLexicalArguments = (context.resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0; + let args: string; + + // An async function is emit as an outer function that calls an inner + // generator function. To preserve lexical bindings, we pass the current + // `this` and `arguments` objects to `__awaiter`. The generator function + // passed to `__awaiter` is executed inside of the callback to the + // promise constructor. + // + // The emit for an async arrow without a lexical `arguments` binding might be: + // + // // input + // let a = async (b) => { await b; } + // + // // output + // let a = (b) => __awaiter(this, void 0, void 0, function* () { + // yield b; + // }); + // + // The emit for an async arrow with a lexical `arguments` binding might be: + // + // // input + // let a = async (b) => { await arguments[0]; } + // + // // output + // let a = (b) => __awaiter(this, arguments, void 0, function* (arguments) { + // yield arguments[0]; + // }); + // + // The emit for an async function expression without a lexical `arguments` binding + // might be: + // + // // input + // let a = async function (b) { + // await b; + // } + // + // // output + // let a = function (b) { + // return __awaiter(this, void 0, void 0, function* () { + // yield b; + // }); + // } + // + // The emit for an async function expression with a lexical `arguments` binding + // might be: + // + // // input + // let a = async function (b) { + // await arguments[0]; + // } + // + // // output + // let a = function (b) { + // return __awaiter(this, arguments, void 0, function* (_arguments) { + // yield _arguments[0]; + // }); + // } + // + // The emit for an async function expression with a lexical `arguments` binding + // and a return type annotation might be: + // + // // input + // let a = async function (b): MyPromise { + // await arguments[0]; + // } + // + // // output + // let a = function (b) { + // return __awaiter(this, arguments, MyPromise, function* (_arguments) { + // yield _arguments[0]; + // }); + // } + // + + // If this is not an async arrow, emit the opening brace of the function body + // and the start of the return statement. + // if (!isArrowFunction) { + // write(" {"); + // increaseIndent(); + // writeLine(); + // write("return"); + // } + + let body = node.body; + let generatorBody: Block; + if (!isBlock(body)) { + let bodyExpr = visitNode(context, body, transformNode); + let returnStmt = factory.createReturnStatement(bodyExpr); + generatorBody = factory.createBlock([returnStmt]); + } + else { + generatorBody = visitNode(context, body, transformNode); + } + + let callExpr = factory.createAwaiterHelperCall(hasLexicalArguments, promiseConstructor, generatorBody); + if (isArrowFunction(node)) { + return callExpr; + } + else { + let returnStmt = factory.createReturnStatement(callExpr); + let newBody = factory.createBlock([returnStmt], /*location*/ body); + return newBody; + } + } + + function transformParameter(context: VisitorContext, node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) { + write(factory.createParameter2( + visitNode(context, node.name, transformNode), + visitNode(context, node.initializer, transformNode), + /*location*/ node, + /*flags*/ node.flags & ~NodeFlags.AccessibilityModifier + )); + } + + function transformVariableStatement(context: VisitorContext, node: VariableStatement, write: (node: Statement) => void) { + // TODO(rbuckton): transform namespace exports for a variable declaration list + Debug.assert(isNamespaceLevelExport(context, node), "Should only reach here for exported variables."); + + let declList = node.declarationList; + context.pushNode(declList); + + let expressions: Expression[]; + for (let varDecl of declList.declarations) { + if (!varDecl.initializer) { + continue; + } + + context.pushNode(varDecl); + + if (isBindingPattern(varDecl.name)) { + Debug.fail("Transform not yet supported."); + } + else { + if (!expressions) { + expressions = []; + } + + let name = getModuleMemberName(context, varDecl); + let initializer = visitNode(context, varDecl.initializer, transformNode); + let assignExpr = factory.createAssignmentExpression(name, initializer); + expressions.push(assignExpr); + } + + context.popNode(); + } + + context.popNode(); + if (expressions) { + let exprStmt = factory.createExpressionStatement(factory.inlineExpressions(expressions)); + write(exprStmt); + } + + } + + function transformModuleDeclaration(context: VisitorContext, node: ModuleDeclaration, write: (node: Statement) => void) { + if (!shouldEmitModuleDeclaration(context, node)) { + return; + } + + let location = node; + if (!isModuleMergedWithClass(context, node)) { + let exportFlags = isTopLevelExport(context, node) ? NodeFlags.Export : undefined; + let varDecl = factory.createVariableDeclaration2(node.name); + let varDecls = factory.createVariableDeclarationList([varDecl]); + let varStmt = factory.createVariableStatement2(varDecls, location, exportFlags); + write(varStmt); + location = undefined; + } + + let localName = context.getGeneratedNameForNode(node); + let localParam = factory.createParameter2(localName); + + let body = node.body; + let moduleBody: Block; + if (isModuleBlock(body)) { + moduleBody = factory.createBlock(visitNodes(context, body.statements, transformModuleElement)); + } + else { + let inner = visitStatement(context, body, transformNode); + moduleBody = isBlock(inner) ? inner : factory.createBlock([inner]); + } + + let funcExpr = factory.createFunctionExpression2(/*name*/ undefined, [localParam], moduleBody); + let parenExpr = factory.createParenthesizedExpression(funcExpr); + let moduleMemberName = getModuleMemberName(context, node); + let moduleStorageObjExpr = factory.createObjectLiteralExpression2(); + let moduleStorageInitExpr = factory.createAssignmentExpression(moduleMemberName, moduleStorageObjExpr); + let moduleStorageExpr = factory.createLogicalOrExpression(moduleMemberName, moduleStorageInitExpr); + let moduleParam: Expression = moduleStorageExpr; + if (isNamespaceLevelExport(context, node)) { + moduleParam = factory.createAssignmentExpression(factory.cloneNode(node.name), moduleStorageExpr); + } + + let callExpr = factory.createCallExpression2(parenExpr, [moduleParam]); + let callStmt = factory.createExpressionStatement(callExpr, location, NodeFlags.GeneratedNamespace); + callStmt.original = node; + write(callStmt); + } + + function shouldEmitModuleDeclaration(context: VisitorContext, node: ModuleDeclaration) { + return isInstantiatedModule(node, context.compilerOptions.preserveConstEnums || context.compilerOptions.isolatedModules); + } + + function isModuleMergedWithClass(context: VisitorContext, node: ModuleDeclaration) { + return !!(context.resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass); } function getExpressionForPropertyName(context: VisitorContext, container: Declaration): Expression { - let name = transformPropertyName(context, container); - if (isComputedPropertyName(name)) { - return name.expression; - } - else if (isStringLiteral(name)) { + let name = container.name; + if (isIdentifier(name)) { return factory.createStringLiteral(name.text); } + else if (isComputedPropertyName(name)) { + return context.getGeneratedNameForNode(name); + } + else { + return factory.cloneNode(name); + } } - function transformPropertyName(context: VisitorContext, container: Declaration, isPerInstance?: boolean): PropertyName { - let name = context.getDeclarationName(container); + function transformPropertyName(context: VisitorContext, container: Declaration): PropertyName { + let name = container.name; if (isComputedPropertyName(name)) { - if (!isPerInstance && context.nodeHasGeneratedName(name)) { - return factory.createIdentifier(context.getGeneratedNameForNode(name)); - } - - let expression = visitExpression(context, name.expression, transformNode); - if (!isPerInstance && nodeCanBeDecorated(container) && nodeIsDecorated(container)) { - let generatedName = factory.createIdentifier(context.getGeneratedNameForNode(name)); + let expression = visitNode(context, name.expression, transformNode); + if (nodeCanBeDecorated(container) && nodeIsDecorated(container)) { + let generatedName = context.getGeneratedNameForNode(name); context.hoistVariableDeclaration(generatedName); - expression = factory.createAssignmentExpression( - generatedName, - expression - ); + expression = factory.createAssignmentExpression(generatedName, expression); + // expression = tag_expression`${generatedName} = ${expression}`; } - return factory.updateComputedPropertyName( - name, - expression - ); + return factory.updateComputedPropertyName(name, expression); } else if (isPropertyName(name)) { - return name; + return factory.cloneNode(name); } Debug.fail("Binding patterns cannot be used as property names."); } - function emitDecoratorsOfClass(context: VisitorContext, node: ClassLikeDeclaration) { - emitDecoratorsOfMembers(context, node, /*isStatic*/ false); - emitDecoratorsOfMembers(context, node, /*isStatic*/ true); - emitDecoratorsOfConstructor(context, node); + function transformEnumDeclaration(context: VisitorContext, node: EnumDeclaration, write: (node: Statement) => void) { + // Const enum declarations may be elided + if (!shouldEmitEnumDeclaration(context, node)) { + return; + } + + let location: TextRange = node; + if (!isNamespaceLevelExport(context, node)) { + let exportFlags = isTopLevelExport(context, node) ? NodeFlags.Export : undefined; + let varDecl = factory.createVariableDeclaration2(node.name, /*initializer*/ undefined, /*location*/ undefined, exportFlags); + let varDecls = factory.createVariableDeclarationList([varDecl]); + let varStmt = factory.createVariableStatement2(varDecls, location); + write(varStmt); + location = undefined; + } + + let localName = context.getGeneratedNameForNode(node); + let enumBody = factory.createBlock([]); + transformEnumMembers(context, node, localName, enumBody.statements); + + let localNameParam = factory.createParameter2(localName); + let enumDecl = factory.createFunctionExpression2(/*name*/ undefined, [localNameParam], enumBody); + let parenExpr = factory.createParenthesizedExpression(enumDecl); + let moduleMemberName = getModuleMemberName(context, node); + let enumStorageObjectExpr = factory.createObjectLiteralExpression2(); + let enumStorageInitExpr = factory.createAssignmentExpression(moduleMemberName, enumStorageObjectExpr); + let enumStorageExpr = factory.createLogicalOrExpression(moduleMemberName, enumStorageInitExpr); + let callExpr = factory.createCallExpression2(parenExpr, [enumStorageExpr]); + let callStmt = factory.createExpressionStatement(callExpr, location); + write(callStmt); + + if (isNamespaceLevelExport(context, node)) { + let varDecl = factory.createVariableDeclaration2(node.name, moduleMemberName); + let varDecls = factory.createVariableDeclarationList([varDecl]); + let varStmt = factory.createVariableStatement2(varDecls); + write(varStmt); + } } - function emitDecoratorsOfMembers(context: VisitorContext, node: ClassLikeDeclaration, isStatic: boolean) { + function transformEnumMembers(context: VisitorContext, node: EnumDeclaration, localName: Identifier, statements: Statement[]) { + for (let member of node.members) { + transformEnumMember(context, member, localName, statements); + } + } + + function transformEnumMember(context: VisitorContext, node: EnumMember, localName: Identifier, statements: Statement[]) { + let enumNameExpr = getExpressionForPropertyName(context, node); + let enumValueExpr = getEnumMemberDeclarationValue(context, node); + let enumNameElemExpr = factory.createElementAccessExpression2(localName, enumNameExpr); + let enumValueAssignExpr = factory.createAssignmentExpression(enumNameElemExpr, enumValueExpr); + let enumValueElemExpr = factory.createElementAccessExpression2(localName, enumValueAssignExpr); + let enumNameAssignExpr = factory.createAssignmentExpression(enumValueElemExpr, enumNameExpr); + let enumMemberStmt = factory.createExpressionStatement(enumNameAssignExpr, /*location*/ node); + statements.push(enumMemberStmt); + } + + function getEnumMemberDeclarationValue(context: VisitorContext, member: EnumMember): Expression { + let value = context.resolver.getConstantValue(member); + if (value !== undefined) { + return factory.createNumericLiteral2(value); + } + else if (member.initializer) { + return visitNode(context, member.initializer, transformNode); + } + else { + // NOTE(rbuckton): Should this be `void 0`? + return factory.createIdentifier("undefined"); + } + } + + function shouldEmitEnumDeclaration(context: VisitorContext, node: EnumDeclaration) { + let isConstEnum = isConst(node); + return !isConstEnum || context.compilerOptions.preserveConstEnums || context.compilerOptions.isolatedModules; + } + + function transformAwaitExpression(context: VisitorContext, node: AwaitExpression, write: (node: Expression) => void) { + let expression = visitNode(context, node.expression, transformNode); + let yieldExpr = factory.createYieldExpression(/*asteriskToken*/ undefined, expression, /*location*/ node); + if (needsParenthesisForAwaitExpressionAsYield(context, node)) { + let parenExpr = factory.createParenthesizedExpression(yieldExpr); + write(parenExpr); + } + else { + write(yieldExpr); + } + } + + function needsParenthesisForAwaitExpressionAsYield(context: VisitorContext, node: AwaitExpression) { + let parentNode = context.parentNode; + if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { + return true; + } + else if (isConditionalExpression(parentNode) && parentNode.condition === node) { + return true; + } + + return false; + } + + function transformDecoratorsOfMembers(context: VisitorContext, node: ClassLikeDeclaration, isStatic: boolean, statements: (node: Statement) => void) { for (let member of node.members) { // only emit members in the correct group if (isStatic !== ((member.flags & NodeFlags.Static) !== 0)) { @@ -508,11 +1053,11 @@ namespace ts.transform { continue; } - emitDecoratorsOfMember(context, node, member); + transformDecoratorsOfMember(context, node, member, statements); } } - function emitDecoratorsOfConstructor(context: VisitorContext, node: ClassLikeDeclaration) { + function transformDecoratorsOfConstructor(context: VisitorContext, node: ClassLikeDeclaration, write: (node: Statement) => void) { let decorators = node.decorators; let constructor = getFirstConstructorWithBody(node); let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated); @@ -536,31 +1081,29 @@ namespace ts.transform { let decoratorExpressions: Expression[] = []; if (decorators) { for (let decorator of decorators) { - decoratorExpressions.push(visitExpression(context, decorator.expression, transformNode)) + decoratorExpressions.push(visitNode(context, decorator.expression, transformNode)) } } if (constructor) { - emitDecoratorsOfParameters(context, constructor.parameters, decoratorExpressions); + appendDecoratorsOfParameters(context, constructor.parameters, decoratorExpressions); } if (context.compilerOptions.emitDecoratorMetadata) { - emitSerializedTypeMetadata(context, node, decoratorExpressions); + appendSerializedTypeMetadata(context, node, decoratorExpressions); } - context.emitAssignmentStatement( - context.getDeclarationName(node), - factory.createCallExpression2( - factory.createIdentifier("__decorate"), - [ - factory.createArrayLiteralExpression(decoratorExpressions), - context.getDeclarationName(node) - ] - ) - ); + let name = context.getDeclarationName(node); + let callExpr = factory.createDecorateHelperCall(decoratorExpressions, name); + let statement = factory.createExpressionStatement(callExpr); + write(statement); + + // statements.push(tag_statement` + // ${name} = __decorate([${decoratorExpressions}], ${name}); + // `); } - function emitDecoratorsOfMember(context: VisitorContext, node: ClassLikeDeclaration, member: ClassElement) { + function transformDecoratorsOfMember(context: VisitorContext, node: ClassLikeDeclaration, member: ClassElement, write: (node: Statement) => void) { let decorators: Decorator[]; let parameters: ParameterDeclaration[]; @@ -627,116 +1170,86 @@ namespace ts.transform { let decoratorExpressions: Expression[] = []; if (decorators) { for (let decorator of decorators) { - decoratorExpressions.push(visitExpression(context, decorator.expression, transformNode)) + decoratorExpressions.push(visitNode(context, decorator.expression, transformNode)) } } if (parameters) { - emitDecoratorsOfParameters(context, parameters, decoratorExpressions); + appendDecoratorsOfParameters(context, parameters, decoratorExpressions); } if (context.compilerOptions.emitDecoratorMetadata) { - emitSerializedTypeMetadata(context, node, decoratorExpressions); + appendSerializedTypeMetadata(context, node, decoratorExpressions); } let prefix = context.getClassMemberPrefix(node, member); - let decorateCallArguments: Expression[] = [ - factory.createArrayLiteralExpression(decoratorExpressions), - prefix, - getExpressionForPropertyName(context, member) - ]; - - let expression: Expression = factory.createCallExpression2( - factory.createIdentifier("__decorate"), - decorateCallArguments - ); - - if (!isPropertyDeclaration(member)) { - decorateCallArguments.push( - factory.createCallExpression2( - factory.createPropertyAccessExpression2( - factory.createIdentifier("Object"), - factory.createIdentifier("getOwnPropertyDescriptor") - ), - [ - prefix, - getExpressionForPropertyName(context, member) - ] - ) - ); - - expression = factory.createCallExpression2( - factory.createPropertyAccessExpression2( - factory.createIdentifier("Object"), - factory.createIdentifier("defineProperty") - ), - [ - prefix, - getExpressionForPropertyName(context, member), - expression - ] - ); + let memberName = getExpressionForPropertyName(context, member); + if (isPropertyDeclaration(member)) { + let decorateExpr = factory.createDecorateHelperCall(decoratorExpressions, prefix, memberName); + let statement = factory.createExpressionStatement(decorateExpr); + write(statement); + // statements.push(tag_statement` + // __decorate([${decoratorExpressions}], ${prefix}, ${memberName}); + // `); + } + else { + let descriptorExpr = factory.createGetOwnPropertyDescriptorCall(prefix, memberName); + let decorateExpr = factory.createDecorateHelperCall(decoratorExpressions, prefix, memberName, descriptorExpr); + let definePropertyExpr = factory.createDefinePropertyCall(prefix, memberName, decorateExpr); + let statement = factory.createExpressionStatement(definePropertyExpr); + write(statement); + // statements.push(tag_statement` + // Object.defineProperty(${prefix}, ${memberName}, + // __decorate([${decoratorExpressions}], ${prefix}, ${memberName}, + // Object.getOwnPropertyDescriptor(${prefix}, ${memberName}))); + // `); } - - context.emitExpressionStatement(expression); } - function emitDecoratorsOfParameters(context: VisitorContext, parameters: ParameterDeclaration[], expressions: Expression[]) { + function appendDecoratorsOfParameters(context: VisitorContext, parameters: ParameterDeclaration[], expressions: Expression[]) { for (let parameterIndex = 0; parameterIndex < parameters.length; parameterIndex++) { let parameter = parameters[parameterIndex]; if (nodeIsDecorated(parameter)) { for (let decorator of parameter.decorators) { - expressions.push( - factory.createCallExpression2( - factory.createIdentifier("__param"), - [ - factory.createNumericLiteral2(parameterIndex), - visitExpression(context, decorator.expression, transformNode) - ] - ) - ); + let decoratorExpr = visitNode(context, decorator.expression, transformNode); + let paramExpr = factory.createParamHelperCall(parameterIndex, decoratorExpr); + expressions.push(paramExpr); + // expressions.push(tag_expression` + // __param(${parameterIndex}, ${decoratorExpr}) + // `); } } } } - function emitSerializedTypeMetadata(context: VisitorContext, node: Declaration, expressions: Expression[]) { - if (shouldEmitTypeMetadata(node)) { - expressions.push( - factory.createCallExpression2( - factory.createIdentifier("__metadata"), - [ - factory.createStringLiteral("design:type"), - // TODO - ] - ) - ); + function appendSerializedTypeMetadata(context: VisitorContext, node: Declaration, expressions: Expression[]) { + if (shouldAppendTypeMetadata(node)) { + let typeExpr = serializeTypeOfNode(context, node); + let metadataExpr = factory.createMetadataHelperCall("design:type", typeExpr); + expressions.push(metadataExpr); + // expressions.push(tag_expression` + // __metadata("design:type", ${serializeTypeOfNode(context, node)}) + // `); } - if (shouldEmitParamTypesMetadata(node)) { - expressions.push( - factory.createCallExpression2( - factory.createIdentifier("__metadata"), - [ - factory.createStringLiteral("design:paramtypes"), - // TODO - ] - ) - ); + if (shouldAppendParamTypesMetadata(node)) { + let paramTypesExpr = serializeParameterTypesOfNode(context, node); + let metadataExpr = factory.createMetadataHelperCall("design:paramtypes", paramTypesExpr); + expressions.push(metadataExpr); + // expressions.push(tag_expression` + // __metadata("design:paramtypes", ${serializeParameterTypesOfNode(context, node)}) + // `); } - if (shouldEmitReturnTypeMetadata(node)) { - expressions.push( - factory.createCallExpression2( - factory.createIdentifier("__metadata"), - [ - factory.createStringLiteral("design:returntype"), - // TODO - ] - ) - ); + if (shouldAppendReturnTypeMetadata(node)) { + let returnTypeExpr = serializeReturnTypeOfNode(context, node); + let metadataExpr = factory.createMetadataHelperCall("design:returntype", returnTypeExpr); + expressions.push(metadataExpr); + // expressions.push(tag_expression` + // __metadata("design:returntype", ${serializeReturnTypeOfNode(context, node)}) + // `); } } - function shouldEmitTypeMetadata(node: Declaration): boolean { + function shouldAppendTypeMetadata(node: Declaration): boolean { // This method determines whether to emit the "design:type" metadata based on the node's kind. // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata // compiler option is set. @@ -751,7 +1264,7 @@ namespace ts.transform { return false; } - function shouldEmitReturnTypeMetadata(node: Declaration): boolean { + function shouldAppendReturnTypeMetadata(node: Declaration): boolean { // This method determines whether to emit the "design:returntype" metadata based on the node's kind. // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata // compiler option is set. @@ -762,7 +1275,7 @@ namespace ts.transform { return false; } - function shouldEmitParamTypesMetadata(node: Declaration): boolean { + function shouldAppendParamTypesMetadata(node: Declaration): boolean { // This method determines whether to emit the "design:paramtypes" metadata based on the node's kind. // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata // compiler option is set. @@ -774,4 +1287,236 @@ namespace ts.transform { } return false; } + + function serializeTypeOfNode(context: VisitorContext, node: Node): Expression { + if (isPropertyDeclaration(node) || isParameter(node) || isGetAccessor(node)) { + return serializeTypeNode(context, node.type); + } + else if (isSetAccessor(node)) { + return serializeTypeNode(context, getSetAccessorTypeAnnotationNode(node)); + } + else if (isClassLike(node) || isFunctionLike(node)) { + return factory.createIdentifier("Function"); + // return tag_id`Function`; + } + else { + return factory.createVoidZeroExpression(); + // return tag_expression`void 0`; + } + } + + function serializeParameterTypesOfNode(context: VisitorContext, node: Node): Expression { + let valueDeclaration = + isClassLike(node) ? getFirstConstructorWithBody(node) : + isFunctionLike(node) && nodeIsPresent(node.body) ? node : + undefined; + + let parameterTypeExpressions: Expression[] = []; + if (valueDeclaration) { + for (let parameter of valueDeclaration.parameters) { + if (parameter.dotDotDotToken) { + let parameterType = parameter.type; + let elementType = + isArrayType(parameterType) ? parameterType.elementType : + isTypeReference(parameterType) && parameterType.typeArguments && singleOrUndefined(parameterType.typeArguments); + parameterTypeExpressions.push(serializeTypeNode(context, elementType)); + } + else { + parameterTypeExpressions.push(serializeTypeOfNode(context, parameter)); + } + } + } + + return factory.createArrayLiteralExpression(parameterTypeExpressions); + } + + function serializeReturnTypeOfNode(context: VisitorContext, node: Node): Expression { + if (isFunctionLike(node)) { + return serializeTypeNode(context, node.type); + } + + return undefined; + } + + function serializeTypeNode(context: VisitorContext, node: TypeNode): Expression { + if (node === undefined) { + return factory.createIdentifier("Object"); + // return tag_id`Object`; + } + + switch (node.kind) { + case SyntaxKind.VoidKeyword: + return factory.createVoidZeroExpression(); + // return tag_expression`void 0`; + + case SyntaxKind.ParenthesizedType: + return serializeTypeNode(context, (node).type); + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return factory.createIdentifier("Function"); + // return tag_id`Function`; + + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + return factory.createIdentifier("Array"); + // return tag_id`Array`; + + case SyntaxKind.TypePredicate: + case SyntaxKind.BooleanKeyword: + return factory.createIdentifier("Boolean") + // return tag_id`Boolean`; + + case SyntaxKind.StringKeyword: + case SyntaxKind.StringLiteral: + return factory.createIdentifier("String"); + // return tag_id`String`; + + case SyntaxKind.NumberKeyword: + return factory.createIdentifier("Number"); + // return tag_id`Number`; + + case SyntaxKind.SymbolKeyword: + return context.languageVersion < ScriptTarget.ES6 + ? getGlobalSymbolNameWithFallback() + : factory.createIdentifier("Symbol"); + // return tag_id`Symbol`; + + case SyntaxKind.TypeReference: + return serializeTypeReferenceNode(context, node); + + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeLiteral: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.AnyKeyword: + break; + + default: + Debug.fail("Cannot serialize unexpected type node."); + break; + } + + return factory.createIdentifier("Object"); + // return tag_id`Object`; + } + + /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ + function serializeTypeReferenceNode(context: VisitorContext, node: TypeReferenceNode) { + let typeName = node.typeName; + let result = context.resolver.getTypeReferenceSerializationKind(node); + switch (result) { + case TypeReferenceSerializationKind.Unknown: + let tempVar = context.declareLocal(); + let globalObjectName = factory.createIdentifier("Object"); + let typeExpr = serializeEntityNameAsExpression(context, typeName, /*useFallback*/ true); + let cacheExpr = factory.createAssignmentExpression(tempVar, typeExpr); + let typeOfExpr = factory.createTypeOfExpression(factory.createParenthesizedExpression(cacheExpr)); + let functionLiteral = factory.createStringLiteral("function"); + let equalityExpr = factory.createStrictEqualityExpression(typeOfExpr, functionLiteral); + let logicalAndExpr = factory.createLogicalAndExpression(equalityExpr, tempVar); + let logicalOrExpr = factory.createLogicalOrExpression(logicalAndExpr, globalObjectName); + return logicalOrExpr; + // return tag_expression` + // typeof (${tempVar} = ${typeExpr}) === "function" && ${tempVar} || Object + // `; + + case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: + return serializeEntityNameAsExpression(context, typeName, /*useFallback*/ false); + + case TypeReferenceSerializationKind.VoidType: + return factory.createVoidZeroExpression(); + // return tag_expression`void 0`; + + case TypeReferenceSerializationKind.BooleanType: + return factory.createIdentifier("Boolean"); + // return tag_id`Boolean`; + + case TypeReferenceSerializationKind.NumberLikeType: + return factory.createIdentifier("Number"); + // return tag_id`Number`; + + case TypeReferenceSerializationKind.StringLikeType: + return factory.createIdentifier("String"); + // return tag_id`String`; + + case TypeReferenceSerializationKind.ArrayLikeType: + return factory.createIdentifier("Array"); + // return tag_id`Array`; + + case TypeReferenceSerializationKind.ESSymbolType: + return context.languageVersion < ScriptTarget.ES6 + ? getGlobalSymbolNameWithFallback() + : factory.createIdentifier("Symbol"); + + case TypeReferenceSerializationKind.TypeWithCallSignature: + return factory.createIdentifier("Function"); + + case TypeReferenceSerializationKind.ObjectType: + default: + break; + } + + return factory.createIdentifier("Object"); + // return tag_id`Object`; + } + + function serializeEntityNameAsExpression(context: VisitorContext, node: EntityName, useFallback: boolean): Expression { + switch (node.kind) { + case SyntaxKind.Identifier: + let name = factory.cloneNode(node); + if (useFallback) { + let undefinedLiteral = factory.createStringLiteral("undefined"); + let typeOfExpr = factory.createTypeOfExpression(name); + let equalityExpr = factory.createStrictInequalityExpression(typeOfExpr, undefinedLiteral); + let logicalAndExpr = factory.createLogicalAndExpression(equalityExpr, name); + return logicalAndExpr; + // return tag_expression` + // typeof ${name} !== "undefined" && ${name} + // `; + } + + return name; + + case SyntaxKind.QualifiedName: + return serializeQualifiedNameAsExpression(context, node, useFallback); + } + } + + function serializeQualifiedNameAsExpression(context: VisitorContext, node: QualifiedName, useFallback: boolean): Expression { + let left: Expression + if (node.left.kind === SyntaxKind.Identifier) { + left = serializeEntityNameAsExpression(context, node.left, useFallback); + } + else if (useFallback) { + let tempVar = context.declareLocal(); + let pathExpr = serializeEntityNameAsExpression(context, node.left, /*useFallback*/ true); + let cacheExpr = factory.createAssignmentExpression(tempVar, pathExpr); + left = factory.createLogicalAndExpression(cacheExpr, tempVar); + // left = tag_expression` + // (${tempVar} = ${pathExpr}) && ${tempVar} + // `; + } + else { + left = serializeEntityNameAsExpression(context, node.left, /*useFallback*/ false); + } + + // we clone the node here to create a copy of the node with no position information + let right = factory.cloneNode(node.right); + let propExpr = factory.createPropertyAccessExpression2(left, right); + return propExpr; + // return tag_expression` + // ${factory.parenthesizeForAccess(left)}.${factory.cloneNode(node.right)} + // `; + } + + function getGlobalSymbolNameWithFallback(): Expression { + let globalSymbolName = factory.createIdentifier("Symbol"); + let globalObjectName = factory.createIdentifier("Object"); + let typeOfExpr = factory.createTypeOfExpression(globalSymbolName); + let functionLiteral = factory.createStringLiteral("function"); + let equalityExpr = factory.createStrictEqualityExpression(typeOfExpr, functionLiteral); + let conditionalExpr = factory.createConditionalExpression2(equalityExpr, globalSymbolName, globalObjectName); + return conditionalExpr; + } } \ No newline at end of file diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index a657cc8c314..8fc69d70e38 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -488,6 +488,14 @@ namespace ts { return Array(paddingLength + 1).join(" "); } } + + declare var global: any, require: any; + if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') { + try { + require("source-map-support").install(); + } + catch (e) { } + } } ts.executeCommandLine(ts.sys.args); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ba5a731e619..35dc62f0849 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -337,7 +337,7 @@ namespace ts { LastKeyword = OfKeyword, FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, - FirstTypeNode = TypeReference, + FirstTypeNode = TypePredicate, LastTypeNode = ParenthesizedType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, @@ -372,6 +372,9 @@ namespace ts { OctalLiteral = 0x00010000, // Octal numeric literal Namespace = 0x00020000, // Namespace declaration ExportContext = 0x00040000, // Export context (initialized by binding) + GeneratedRest = 0x00080000, // Synthetic node generated during transformation + GeneratedSuper = 0x00100000, // Synthetic node generated during transformation + GeneratedNamespace =0x00200000, // Synthetic node generated during transformation Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async, AccessibilityModifier = Public | Private | Protected, @@ -433,56 +436,51 @@ namespace ts { ContainsTypeScript = 1 << 2, ContainsTypeScriptPropertyDeclarationWithInitializer = 1 << 3, ContainsTypeScriptClassSyntaxExtension = 1 << 4, - ContainsTypeScriptGeneratedStatements = 1 << 5, + ContainsTypeScriptDecorator = 1 << 6, // A fact that states that a node is ES6 syntax - ES6 = 1 << 6, + ES6 = 1 << 7, // A fact that states that this node or its subtree contains ES6 syntax - ContainsES6 = 1 << 7, + ContainsES6 = 1 << 8, - ContainsES6Yield = 1 << 8, + ContainsES6Yield = 1 << 9, // A fact that states that this node or its subtree contains an ES6 Binding Pattern - ContainsES6BindingPattern = 1 << 9, + ContainsES6ParameterBindingPattern = 1 << 10, + ContainsES6VariableBindingPattern = 1 << 11, // A fact that states that this node or its subtree contains an ES6 Rest Parameter - ContainsES6RestParameter = 1 << 10, + ContainsES6RestParameter = 1 << 12, // A fact that states that this node or its subtree contains an ES6 Parameter Initializer - ContainsES6ParameterInitializer = 1 << 11, + ContainsES6ParameterInitializer = 1 << 13, - ContainsES6SpreadElement = 1 << 12, + ContainsES6SpreadElement = 1 << 14, - ContainsES6LetOrConst = 1 << 13, + ContainsES6LetOrConst = 1 << 15, + + ContainsES6ComputedPropertyName = 1 << 16, // A fact that states that this node or its subtree contains a captured lexical `this` binding - ContainsCapturedThis = 1 << 14, + ContainsCapturedThis = 1 << 17, // A fact that states that this node or its subtree contains a lexical `this` binding - ContainsLexicalThis = 1 << 15, + ContainsLexicalThis = 1 << 18, - ContainsHoistedDeclarationInES6Generator = 1 << 16, - ContainsCompletionStatementInES6Genertator = 1 << 17, + ContainsHoistedDeclaration = 1 << 19, + ContainsCompletionStatement = 1 << 20, + + // Template Transform Facts + ContainsTemplatePlaceholder = 1 << 21, // // Assertions // ThisNodeIsTypeScript = TypeScript | ContainsTypeScript, - ThisNodeIsTypeScriptAccessibilityModifier = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptOverload = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptPropertyDeclaration = ThisNodeIsTypeScript | ContainsTypeScriptClassSyntaxExtension, - ThisNodeIsTypeScriptPropertyDeclarationWithInitializer = ThisNodeIsTypeScriptPropertyDeclaration | ContainsTypeScriptPropertyDeclarationWithInitializer, - ThisNodeIsTypeScriptAmbientDeclaration = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptParameterPropertyAssignment = ThisNodeIsTypeScript | ContainsTypeScriptClassSyntaxExtension, - ThisNodeIsTypeScriptOptionalParameter = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptClassWithSyntaxExtensions = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptEnumDeclaration = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptModuleDeclaration = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptImportEqualsDeclaration = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptExportAssignmentDeclaration = ThisNodeIsTypeScript, - ThisNodeIsTypeScriptDecorator = ThisNodeIsTypeScript, + ThisNodeIsTypeScriptClassSyntaxExtension = ThisNodeIsTypeScript | ContainsTypeScriptClassSyntaxExtension, + ThisNodeIsTypeScriptDecorator = ThisNodeIsTypeScriptClassSyntaxExtension | ContainsTypeScriptDecorator, // Asserts that this node is ES6, and any subtree that contains it contains ES6. ThisNodeIsES6 = ES6 | ContainsES6, @@ -491,7 +489,8 @@ namespace ts { // Asserts that this node is ES6, and any subtree that contains it contains an // ES6 binding pattern. - ThisNodeIsES6BindingPattern = ThisNodeIsES6 | ContainsES6BindingPattern, + ThisNodeIsES6ParameterBindingPattern = ThisNodeIsES6 | ContainsES6ParameterBindingPattern, + ThisNodeIsES6VariableBindingPattern = ThisNodeIsES6 | ContainsES6VariableBindingPattern, // Asserts that this node is ES6, and any subtree that contains it contains an // ES6 rest parameter. @@ -503,30 +502,12 @@ namespace ts { ThisNodeIsES6SpreadElement = ThisNodeIsES6 | ContainsES6SpreadElement, ThisNodeIsES6LetOrConst = ThisNodeIsES6 | ContainsES6LetOrConst, - ThisNodeIsES6ArrowFunction = ThisNodeIsES6, - ThisNodeIsES6Generator = ThisNodeIsES6, - ThisNodeIsES6MethodDeclaration = ThisNodeIsES6, - ThisNodeIsES6DestructuringAssignment = ThisNodeIsES6, - ThisNodeIsES6ComputedPropertyName = ThisNodeIsES6, - ThisNodeIsES6ShorthandPropertyAssignment = ThisNodeIsES6, - ThisNodeIsES6ForOfStatement = ThisNodeIsES6, - ThisNodeIsES6ImportDeclaration = ThisNodeIsES6, - ThisNodeIsES6ExportDeclaration = ThisNodeIsES6, - ThisNodeIsES6Export = ThisNodeIsES6, - ThisNodeIsES6NoSubstitutionTemplateLiteral = ThisNodeIsES6, - ThisNodeIsES6TemplateExpression = ThisNodeIsES6, - ThisNodeIsES6TaggedTemplateExpression = ThisNodeIsES6, - ThisNodeIsES6BinaryOrOctalLiteralExpression = ThisNodeIsES6, - - // Asserts that this node is ES6, and any subtree that contains it contains an - // ES6 class expression or declaration. - ThisNodeIsES6Class = ThisNodeIsES6, // Additional markers ThisNodeCapturesLexicalThis = ContainsCapturedThis, ThisNodeIsThisKeyword = ContainsLexicalThis, - ThisNodeIsHoistedDeclarationInGenerator = ContainsHoistedDeclarationInES6Generator, - ThisNodeIsCompletionStatementInGenerator = ContainsCompletionStatementInES6Genertator, + ThisNodeIsHoistedDeclaration = ContainsHoistedDeclaration, + ThisNodeIsCompletionStatement = ContainsCompletionStatement, // // Masks @@ -538,24 +519,18 @@ namespace ts { ThisNodeIsES6Mask = ES6, - // Mask used to clear transform flags that only apply to a node and not a subtree. - ThisNodeFlags = - ThisNodeIsTypeScriptMask | - ThisNodeIsES6Mask, - // // Transformation Tests // ThisNodeNeedsTransformToES6 = - ThisNodeIsTypeScriptMask | - ContainsTypeScriptGeneratedStatements, + ThisNodeIsTypeScriptMask, ThisNodeNeedsTransformToES5 = ThisNodeIsES6Mask, - // - // Questions + // + // Queries // SubtreeContainsTypeScript = @@ -564,9 +539,6 @@ namespace ts { SubtreeNeedsTransformToES6 = SubtreeContainsTypeScript, - - SubtreeContainsTypeScriptGeneratedStatements = - ContainsTypeScriptGeneratedStatements, SubtreeContainsLexicalThis = ContainsLexicalThis, @@ -577,9 +549,12 @@ namespace ts { SubtreeContainsRestParameter = ContainsES6RestParameter, - SubtreeContainsBindingPattern = - ContainsES6BindingPattern, + SubtreeContainsParameterBindingPattern = + ContainsES6ParameterBindingPattern, + SubtreeContainsVariableBindingPattern = + ContainsES6VariableBindingPattern, + SubtreeContainsParameterInitializer = ContainsES6ParameterInitializer, @@ -595,23 +570,38 @@ namespace ts { SubtreeNeedsTransformToES5, ThisParameterNeedsTransform = - ContainsES6BindingPattern | + ContainsES6VariableBindingPattern | + ContainsES6ParameterBindingPattern | ContainsES6RestParameter | ContainsES6ParameterInitializer, + SubtreeContainsES6ParameterOrCapturedThis = + ContainsES6ParameterBindingPattern | + ContainsES6ParameterInitializer | + ContainsES6RestParameter | + ContainsCapturedThis, + + SubtreeContainsTemplatePlaceholder = + ContainsTemplatePlaceholder, + // // Scope Exclusions // + + NodeExcludes = + ThisNodeIsTypeScriptMask | + ThisNodeIsES6Mask, ArrowFunctionScopeExcludes = - ContainsTypeScriptGeneratedStatements | ContainsES6Yield | - ContainsES6BindingPattern | + ContainsES6VariableBindingPattern | + ContainsES6ParameterBindingPattern | ContainsES6RestParameter | ContainsES6ParameterInitializer | ContainsES6LetOrConst | - ContainsHoistedDeclarationInES6Generator | - ContainsCompletionStatementInES6Genertator, + ContainsHoistedDeclaration | + ContainsCompletionStatement | + ContainsLexicalThis, FunctionScopeExcludes = ArrowFunctionScopeExcludes | @@ -621,18 +611,17 @@ namespace ts { ClassScopeExcludes = ContainsLexicalThis | ContainsCapturedThis | - ContainsES6BindingPattern | - ContainsTypeScriptClassSyntaxExtension, + ContainsES6VariableBindingPattern | + ContainsES6ParameterBindingPattern | + ContainsTypeScriptClassSyntaxExtension | + ContainsTypeScriptDecorator, ModuleScopeExcludes = - ContainsTypeScriptGeneratedStatements | ContainsES6LetOrConst | ContainsLexicalThis | ContainsCapturedThis | - ContainsES6BindingPattern, - - BlockScopeExcludes = - ContainsTypeScriptGeneratedStatements, + ContainsES6VariableBindingPattern | + ContainsES6ParameterBindingPattern, CallOrArrayLiteralExcludes = ContainsES6SpreadElement, @@ -679,6 +668,7 @@ namespace ts { // Only set when the parser was in some interesting context (like async/yield). /* @internal */ parserContextFlags?: ParserContextFlags; /* @internal */ transformFlags?: TransformFlags; + /* @internal */ excludeTransformFlags?: TransformFlags; decorators?: NodeArray; // Array of decorators (in document order) modifiers?: ModifiersArray; // Array of modifiers /* @internal */ id?: number; // Unique id (used to look up NodeLinks) @@ -784,6 +774,8 @@ namespace ts { } // @kind(SyntaxKind.VariableDeclaration) + // @factoryhidden("decorators", true) + // @factoryhidden("modifiers", true) export interface VariableDeclaration extends Declaration { // @factoryhidden parent?: VariableDeclarationList; @@ -803,7 +795,6 @@ namespace ts { // @factoryparam dotDotDotToken?: Node; // Present on rest parameter name: Identifier | BindingPattern; // Declared parameter name - // @factoryparam questionToken?: Node; // Present on optional parameter type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer @@ -844,10 +835,10 @@ namespace ts { // @kind(SyntaxKind.PropertyAssignment) // @factoryhidden("decorators", true) // @factoryhidden("modifiers", true) + // @factoryhidden("questionToken", true) export interface PropertyAssignment extends ObjectLiteralElement { _propertyAssignmentBrand: any; name: PropertyName; - // @factoryparam questionToken?: Node; initializer: Expression; } @@ -855,9 +846,9 @@ namespace ts { // @kind(SyntaxKind.ShorthandPropertyAssignment) // @factoryhidden("decorators", true) // @factoryhidden("modifiers", true) + // @factoryhidden("questionToken", true) export interface ShorthandPropertyAssignment extends ObjectLiteralElement { name: Identifier; - // @factoryparam questionToken?: Node; } @@ -905,7 +896,7 @@ namespace ts { // @factoryparam questionToken?: Node; - // @visitor("visitBlockOrExpressionInNewLexicalScope") + // @visitor("visitBlockOrExpressionInNewLexicalEnvironment") body?: Block | Expression; } @@ -915,7 +906,7 @@ namespace ts { export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement { name?: Identifier; - // @visitor("visitBlockInNewLexicalScope") + // @visitor("visitBlockInNewLexicalEnvironment") body?: Block; } @@ -971,7 +962,7 @@ namespace ts { export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { _accessorDeclarationBrand: any; name: PropertyName; - // @visitor("visitBlockInNewLexicalScope") + // @visitor("visitBlockInNewLexicalEnvironment") body: Block; } @@ -1108,11 +1099,6 @@ namespace ts { _postfixExpressionBrand: any; } - // @kind(SyntaxKind.TrueKeyword, { create: false }) - // @kind(SyntaxKind.FalseKeyword, { create: false }) - // @kind(SyntaxKind.NullKeyword, { create: false }) - // @kind(SyntaxKind.ThisKeyword) - // @kind(SyntaxKind.SuperKeyword, { create: false }) export interface LeftHandSideExpression extends PostfixExpression { _leftHandSideExpressionBrand: any; } @@ -1121,6 +1107,11 @@ namespace ts { _memberExpressionBrand: any; } + // @kind(SyntaxKind.TrueKeyword) + // @kind(SyntaxKind.FalseKeyword) + // @kind(SyntaxKind.NullKeyword, { create: false }) + // @kind(SyntaxKind.ThisKeyword) + // @kind(SyntaxKind.SuperKeyword) export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } @@ -1177,7 +1168,7 @@ namespace ts { export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration { name?: Identifier; - // @visitor("visitBlockOrExpressionInNewLexicalScope") + // @visitor("visitBlockOrExpressionInNewLexicalEnvironment") body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional } @@ -1372,6 +1363,8 @@ namespace ts { } // @kind(SyntaxKind.VariableStatement) + // @factoryhidden("decorators", false) + // @factoryhidden("modifiers", false) export interface VariableStatement extends Statement { declarationList: VariableDeclarationList; } @@ -1384,11 +1377,16 @@ namespace ts { // @kind(SyntaxKind.IfStatement) export interface IfStatement extends Statement { expression: Expression; + + // @visitor("visitStatement") thenStatement: Statement; + + // @visitor("visitStatement") elseStatement?: Statement; } export interface IterationStatement extends Statement { + // @visitor("visitStatement") statement: Statement; } @@ -1440,6 +1438,8 @@ namespace ts { // @kind(SyntaxKind.WithStatement) export interface WithStatement extends Statement { expression: Expression; + + // @visitor("visitStatement") statement: Statement; } @@ -1470,6 +1470,8 @@ namespace ts { // @kind(SyntaxKind.LabeledStatement) export interface LabeledStatement extends Statement { label: Identifier; + + // @visitor("visitStatement") statement: Statement; } @@ -1531,6 +1533,7 @@ namespace ts { // @kind(SyntaxKind.HeritageClause) export interface HeritageClause extends Node { + // @factoryparam token: SyntaxKind; types?: NodeArray; } @@ -1562,7 +1565,7 @@ namespace ts { export interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; - // @visitor("visitModuleBlockOrModuleDeclarationInNewLexicalScope") + // @visitor("visitModuleBlockOrModuleDeclarationInNewLexicalEnvironment") body: ModuleBlock | ModuleDeclaration; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bfcac875ec5..32d7b2c611b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -11,7 +11,7 @@ namespace ts { export interface SynthesizedNode extends Node { leadingCommentRanges?: CommentRange[]; trailingCommentRanges?: CommentRange[]; - startsOnNewLine: boolean; + startsOnNewLine?: boolean; } export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { @@ -435,12 +435,22 @@ namespace ts { /** Gets the original node for a node that was updated via one of the factory.updateX functions */ export function getOriginalNode(node: Node) { - while (node.original) { + while (node && node.original) { node = node.original; } return node; } + + export function getOriginalNodeIf(node: T, nodeTest: (node: Node) => node is T): T { + while (node && node.original) { + let original = node.original; + if (nodeTest(original)) { + node = original; + } + } + return node; + } export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { // If parameter/type parameter, the prev token trailing comments are part of this node too @@ -651,11 +661,11 @@ namespace ts { return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor); } - export function isClassLike(node: Node): boolean { + export function isClassLike(node: Node): node is ClassLikeDeclaration { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } - export function isFunctionLike(node: Node): boolean { + export function isFunctionLike(node: Node): node is FunctionLikeDeclaration { if (node) { switch (node.kind) { case SyntaxKind.Constructor: @@ -685,27 +695,33 @@ namespace ts { return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression; } - export function getContainingFunction(node: Node): FunctionLikeDeclaration { + export function getContainingFunction(node: Node): FunctionLikeDeclaration; + export function getContainingFunction(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): FunctionLikeDeclaration; + export function getContainingFunction(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): FunctionLikeDeclaration { while (true) { - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; if (!node || isFunctionLike(node)) { return node; } } } - export function getContainingClass(node: Node): ClassLikeDeclaration { + export function getContainingClass(node: Node): ClassLikeDeclaration; + export function getContainingClass(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): ClassLikeDeclaration; + export function getContainingClass(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): ClassLikeDeclaration { while (true) { - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; if (!node || isClassLike(node)) { return node; } } } - export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { + export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node; + export function getThisContainer(node: Node, includeArrowFunctions: boolean, getAncestorOrSelf: (offset: number) => Node, offset: number): Node; + export function getThisContainer(node: Node, includeArrowFunctions: boolean, getAncestorOrSelf?: (offset: number) => Node, offset?: number): Node { while (true) { - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; if (!node) { return undefined; } @@ -715,7 +731,7 @@ namespace ts { // 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(node.parent.parent)) { + if (isClassLike(getAncestorOrSelf ? getAncestorOrSelf(offset + 2) : node.parent.parent)) { return node; } // If this is a computed property, then the parent should not @@ -723,19 +739,20 @@ namespace ts { // in an object literal, like a method or accessor. But in order for // such a parent to be a this container, the reference must be in // the *body* of the container. - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. - if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) { + if (isParameter(getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent) + && isClassElement(getAncestorOrSelf ? getAncestorOrSelf(offset + 2) : node.parent.parent)) { // If the decorator's parent is a Parameter, we resolve the this container from // the grandparent class declaration. - node = node.parent.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(offset += 2) : node.parent.parent; } - else if (isClassElement(node.parent)) { + else if (isClassElement(getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent)) { // If the decorator's parent is a class element, we resolve the 'this' container // from the parent class declaration. - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; } break; case SyntaxKind.ArrowFunction: @@ -760,9 +777,11 @@ namespace ts { } } - export function getSuperContainer(node: Node, includeFunctions: boolean): Node { + export function getSuperContainer(node: Node, includeFunctions: boolean): Node; + export function getSuperContainer(node: Node, includeFunctions: boolean, getAncestorOrSelf: (offset: number) => Node, offset: number): Node; + export function getSuperContainer(node: Node, includeFunctions: boolean, getAncestorOrSelf?: (offset: number) => Node, offset?: number): Node { while (true) { - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; if (!node) return node; switch (node.kind) { case SyntaxKind.ComputedPropertyName: @@ -770,7 +789,7 @@ namespace ts { // 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(node.parent.parent)) { + if (isClassLike(getAncestorOrSelf ? getAncestorOrSelf(offset + 2) : node.parent.parent)) { return node; } // If this is a computed property, then the parent should not @@ -778,19 +797,20 @@ namespace ts { // in an object literal, like a method or accessor. But in order for // such a parent to be a super container, the reference must be in // the *body* of the container. - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. - if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) { + if (isParameter(getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent) + && isClassElement(getAncestorOrSelf ? getAncestorOrSelf(offset + 2) : node.parent.parent)) { // If the decorator's parent is a Parameter, we resolve the this container from // the grandparent class declaration. - node = node.parent.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(offset += 2) : node.parent.parent; } - else if (isClassElement(node.parent)) { + else if (isClassElement(getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent)) { // If the decorator's parent is a class element, we resolve the 'this' container // from the parent class declaration. - node = node.parent; + node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent; } break; case SyntaxKind.FunctionDeclaration: @@ -872,7 +892,7 @@ namespace ts { export function nodeIsDecorated(node: Node): boolean { switch (node.kind) { case SyntaxKind.ClassDeclaration: - if (node.decorators) { + if (node.decorators && node.decorators.length > 0) { return true; } @@ -880,14 +900,14 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: - if (node.decorators) { + if (node.decorators && node.decorators.length > 0) { return true; } return false; case SyntaxKind.GetAccessor: - if ((node).body && node.decorators) { + if ((node).body && node.decorators && node.decorators.length > 0) { return true; } @@ -895,7 +915,7 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.SetAccessor: - if ((node).body && node.decorators) { + if ((node).body && node.decorators && node.decorators.length > 0) { return true; } @@ -926,7 +946,7 @@ namespace ts { * Returns whether the node is part of an expression. * @param node The node to test */ - export function isExpression(node: Node): boolean; + export function isPartOfExpression(node: Node): boolean; /** * Returns whether the node is part of an expression. @@ -936,7 +956,7 @@ namespace ts { * @param offset The offset in the node stack used to get the ancestor of the current node * from the emitter's node stack. */ - export function isExpression(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): boolean; + export function isPartOfExpression(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): boolean; /** * Returns whether the node is part of an expression. @@ -953,7 +973,7 @@ namespace ts { * current node on the top of the node stack, an offset of one (1) refers to its parent, an * offset of two (2) refers to the grandparent, and so on. */ - export function isExpression(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): boolean { + export function isPartOfExpression(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): boolean { let parent: Node; switch (node.kind) { case SyntaxKind.ThisKeyword: @@ -1049,7 +1069,7 @@ namespace ts { case SyntaxKind.ExpressionWithTypeArguments: return (parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent, getAncestorOrSelf, offset + 1); default: - if (isExpression(parent, getAncestorOrSelf, offset)) { + if (isPartOfExpression(parent, getAncestorOrSelf, offset)) { return true; } } @@ -1057,6 +1077,150 @@ namespace ts { return false; } + export function getExpressionPrecedence(expr: Expression) { + return getOperatorPrecedence(expr.kind, getOperator(expr), isNewExpression(expr) && !expr.arguments) + } + + export function getBinaryOperatorPrecedence(operator: SyntaxKind) { + return getOperatorPrecedence(SyntaxKind.BinaryExpression, operator); + } + + function getOperator(expr: Expression) { + return isBinaryExpression(expr) + ? expr.operatorToken.kind + : isPrefixUnaryExpression(expr) || isPostfixUnaryExpression(expr) + ? expr.operator + : undefined; + } + + function getOperatorPrecedence(kind: SyntaxKind, operator: SyntaxKind, isNewExpressionWithoutArguments?: boolean) { + switch (kind) { + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + return 19; + + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + return 18; + + case SyntaxKind.NewExpression: + return isNewExpressionWithoutArguments ? 17 : 18; + + case SyntaxKind.CallExpression: + return 17; + + case SyntaxKind.PostfixUnaryExpression: + return 16; + + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.AwaitExpression: + return 15; + + case SyntaxKind.BinaryExpression: + switch (operator) { + case SyntaxKind.ExclamationToken: + case SyntaxKind.TildeToken: + return 15; + + case SyntaxKind.AsteriskToken: + case SyntaxKind.SlashToken: + case SyntaxKind.PercentToken: + return 14; + + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + return 13; + + case SyntaxKind.LessThanLessThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + return 12; + + case SyntaxKind.LessThanToken: + case SyntaxKind.LessThanEqualsToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.GreaterThanEqualsToken: + case SyntaxKind.InKeyword: + case SyntaxKind.InstanceOfKeyword: + return 11; + + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + return 10; + + case SyntaxKind.AmpersandToken: + return 9; + + case SyntaxKind.CaretToken: + return 8; + + case SyntaxKind.BarToken: + return 7; + + case SyntaxKind.AmpersandAmpersandToken: + return 6; + + case SyntaxKind.BarBarToken: + return 5; + + case SyntaxKind.EqualsToken: + case SyntaxKind.PlusEqualsToken: + case SyntaxKind.MinusEqualsToken: + case SyntaxKind.AsteriskEqualsToken: + case SyntaxKind.SlashEqualsToken: + case SyntaxKind.PercentEqualsToken: + case SyntaxKind.LessThanLessThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.AmpersandEqualsToken: + case SyntaxKind.CaretEqualsToken: + case SyntaxKind.BarEqualsToken: + return 3; + + case SyntaxKind.CommaToken: + return 0; + + default: + return -1; + } + + case SyntaxKind.ConditionalExpression: + return 4; + + case SyntaxKind.YieldExpression: + return 2; + + case SyntaxKind.SpreadElementExpression: + return 1; + + default: + return -1; + } + } + export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { let moduleState = getModuleInstanceState(node); return moduleState === ModuleInstanceState.Instantiated || @@ -1262,7 +1426,7 @@ namespace ts { case SyntaxKind.LabeledStatement: case SyntaxKind.ReturnStatement: case SyntaxKind.SwitchStatement: - case SyntaxKind.ThrowKeyword: + case SyntaxKind.ThrowStatement: case SyntaxKind.TryStatement: case SyntaxKind.VariableStatement: case SyntaxKind.WhileStatement: @@ -1275,8 +1439,12 @@ namespace ts { return false; } + export function isStatementOrDeclarationStatement(n: Node): n is Statement { + return isStatement(n) || isDeclarationStatement(n); + } + // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationName(name: Node): boolean { + export function isDeclarationName(name: Node): name is Identifier | StringLiteral | LiteralExpression { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -2017,7 +2185,7 @@ namespace ts { return 0; } - export function isLeftHandSideExpression(expr: Node): boolean { + export function isLeftHandSideExpression(expr: Node): expr is LeftHandSideExpression { if (expr) { switch (expr.kind) { case SyntaxKind.PropertyAccessExpression: diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 27cb3574473..eab52af6bdf 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -29,7 +29,7 @@ class TypeWriterWalker { } private visitNode(node: ts.Node): void { - if (ts.isExpression(node) || node.kind === ts.SyntaxKind.Identifier) { + if (ts.isPartOfExpression(node) || node.kind === ts.SyntaxKind.Identifier) { this.logTypeAndSymbol(node); } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 227ba6a7970..8e9e816176d 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -59,7 +59,7 @@ namespace ts.BreakpointResolver { function spanInNode(node: Node): TextSpan { if (node) { - if (isExpression(node)) { + if (isPartOfExpression(node)) { if (node.parent.kind === SyntaxKind.DoStatement) { // Set span as if on while keyword return spanInPreviousNode(node); diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 1a758886350..19ce73288bc 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -681,7 +681,7 @@ namespace ts.formatting { } static NodeIsInDecoratorContext(node: Node): boolean { - while (isExpression(node)) { + while (isPartOfExpression(node)) { node = node.parent; } return node.kind === SyntaxKind.Decorator; diff --git a/tests/baselines/reference/anyAssignabilityInInheritance.js b/tests/baselines/reference/anyAssignabilityInInheritance.js index 04e3e91761d..123d46485ad 100644 --- a/tests/baselines/reference/anyAssignabilityInInheritance.js +++ b/tests/baselines/reference/anyAssignabilityInInheritance.js @@ -129,7 +129,6 @@ var CC = (function () { } return CC; })(); -var CC; (function (CC) { CC.bar = 1; })(CC || (CC = {})); diff --git a/tests/baselines/reference/anyAssignableToEveryType2.js b/tests/baselines/reference/anyAssignableToEveryType2.js index 530d8eb0439..81ad2cbd468 100644 --- a/tests/baselines/reference/anyAssignableToEveryType2.js +++ b/tests/baselines/reference/anyAssignableToEveryType2.js @@ -156,7 +156,6 @@ var c = (function () { } return c; })(); -var c; (function (c) { c.bar = 1; })(c || (c = {})); diff --git a/tests/baselines/reference/asyncAwaitIsolatedModules_es6.js b/tests/baselines/reference/asyncAwaitIsolatedModules_es6.js index 7007c66ae28..9f3005e5861 100644 --- a/tests/baselines/reference/asyncAwaitIsolatedModules_es6.js +++ b/tests/baselines/reference/asyncAwaitIsolatedModules_es6.js @@ -42,7 +42,7 @@ module M { //// [asyncAwaitIsolatedModules_es6.js] var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) { return new Promise(function (resolve, reject) { - generator = generator.call(thisArg, _arguments); + generator = generator.apply(thisArg, _arguments); function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); } function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } } function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } } diff --git a/tests/baselines/reference/asyncAwait_es6.js b/tests/baselines/reference/asyncAwait_es6.js index 155a44d339d..fb4dbf9955d 100644 --- a/tests/baselines/reference/asyncAwait_es6.js +++ b/tests/baselines/reference/asyncAwait_es6.js @@ -42,7 +42,7 @@ module M { //// [asyncAwait_es6.js] var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) { return new Promise(function (resolve, reject) { - generator = generator.call(thisArg, _arguments); + generator = generator.apply(thisArg, _arguments); function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); } function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } } function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } } diff --git a/tests/baselines/reference/classExpressionES61.js b/tests/baselines/reference/classExpressionES61.js index afef0909039..eaf013acbaf 100644 --- a/tests/baselines/reference/classExpressionES61.js +++ b/tests/baselines/reference/classExpressionES61.js @@ -3,5 +3,4 @@ var v = class C {}; //// [classExpressionES61.js] var v = class C { -} -; +}; diff --git a/tests/baselines/reference/classExpressionES62.js b/tests/baselines/reference/classExpressionES62.js index 79cede7300d..620d86c6de2 100644 --- a/tests/baselines/reference/classExpressionES62.js +++ b/tests/baselines/reference/classExpressionES62.js @@ -6,5 +6,4 @@ var v = class C extends D {}; class D { } var v = class C extends D { -} -; +}; diff --git a/tests/baselines/reference/classExpressionES63.js b/tests/baselines/reference/classExpressionES63.js index 6d357af7c5a..0ee59314810 100644 --- a/tests/baselines/reference/classExpressionES63.js +++ b/tests/baselines/reference/classExpressionES63.js @@ -11,20 +11,17 @@ let C = class class_1 extends class class_2 extends class class_3 { constructor() { this.a = 1; } -} - { +} { constructor(...args) { super(...args); this.b = 2; } -} - { +} { constructor(...args) { super(...args); this.c = 3; } -} -; +}; let c = new C(); c.a; c.b; diff --git a/tests/baselines/reference/generatorTypeCheck55.js b/tests/baselines/reference/generatorTypeCheck55.js index dd7cd33af29..4943791d354 100644 --- a/tests/baselines/reference/generatorTypeCheck55.js +++ b/tests/baselines/reference/generatorTypeCheck55.js @@ -6,6 +6,5 @@ function* g() { //// [generatorTypeCheck55.js] function* g() { var x = class C extends (yield) { - } - ; + }; } diff --git a/tests/baselines/reference/generatorTypeCheck56.js b/tests/baselines/reference/generatorTypeCheck56.js index c1b0f98f5e7..9d8d00e01e7 100644 --- a/tests/baselines/reference/generatorTypeCheck56.js +++ b/tests/baselines/reference/generatorTypeCheck56.js @@ -13,6 +13,5 @@ function* g() { *[yield 0]() { yield 0; } - } - ; + }; } diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 4dac77c3f6f..62df78c21dd 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -24,7 +24,8 @@ module ts { `{ "kind": "JSDocUnknownType", "pos": 1, - "end": 2 + "end": 2, + "transformFlags": 0 }`); }); @@ -33,7 +34,8 @@ module ts { `{ "kind": "JSDocAllType", "pos": 1, - "end": 2 + "end": 2, + "transformFlags": 0 }`); }); @@ -43,10 +45,12 @@ module ts { "kind": "JSDocNullableType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 } }`) }); @@ -57,10 +61,12 @@ module ts { "kind": "JSDocNullableType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "transformFlags": 0 } }`) }); @@ -71,10 +77,12 @@ module ts { "kind": "JSDocNonNullableType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 } }`) }); @@ -85,10 +93,12 @@ module ts { "kind": "JSDocNonNullableType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "transformFlags": 0 } }`) }); @@ -99,6 +109,7 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 3, + "transformFlags": 0, "members": { "length": 0, "pos": 2, @@ -113,15 +124,18 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 6, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 5, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" } }, @@ -138,21 +152,25 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 14, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 13, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" }, "type": { "kind": "NumberKeyword", "pos": 6, - "end": 13 + "end": 13, + "transformFlags": 0 } }, "length": 1, @@ -168,15 +186,18 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 11, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 5, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" } }, @@ -184,10 +205,12 @@ module ts { "kind": "JSDocRecordMember", "pos": 6, "end": 10, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 6, "end": 10, + "transformFlags": 0, "text": "bar" } }, @@ -204,31 +227,37 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 19, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 13, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" }, "type": { "kind": "NumberKeyword", "pos": 6, - "end": 13 + "end": 13, + "transformFlags": 0 } }, "1": { "kind": "JSDocRecordMember", "pos": 14, "end": 18, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 14, "end": 18, + "transformFlags": 0, "text": "bar" } }, @@ -245,15 +274,18 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 19, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 5, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" } }, @@ -261,16 +293,19 @@ module ts { "kind": "JSDocRecordMember", "pos": 6, "end": 18, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 6, "end": 10, + "transformFlags": 0, "text": "bar" }, "type": { "kind": "NumberKeyword", "pos": 11, - "end": 18 + "end": 18, + "transformFlags": 0 } }, "length": 2, @@ -286,37 +321,44 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 27, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 13, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 5, + "transformFlags": 0, "text": "foo" }, "type": { "kind": "NumberKeyword", "pos": 6, - "end": 13 + "end": 13, + "transformFlags": 0 } }, "1": { "kind": "JSDocRecordMember", "pos": 14, "end": 26, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 14, "end": 18, + "transformFlags": 0, "text": "bar" }, "type": { "kind": "NumberKeyword", "pos": 19, - "end": 26 + "end": 26, + "transformFlags": 0 } }, "length": 2, @@ -332,15 +374,18 @@ module ts { "kind": "JSDocRecordType", "pos": 1, "end": 11, + "transformFlags": 0, "members": { "0": { "kind": "JSDocRecordMember", "pos": 2, "end": 10, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 2, "end": 10, + "transformFlags": 0, "originalKeywordKind": "FunctionKeyword", "text": "function" } @@ -358,16 +403,19 @@ module ts { "kind": "JSDocUnionType", "pos": 1, "end": 16, + "transformFlags": 0, "types": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 }, "1": { "kind": "StringKeyword", "pos": 9, - "end": 15 + "end": 15, + "transformFlags": 0 }, "length": 2, "pos": 2, @@ -382,16 +430,19 @@ module ts { "kind": "JSDocUnionType", "pos": 1, "end": 14, + "transformFlags": 0, "types": { "0": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "transformFlags": 0 }, "1": { "kind": "StringKeyword", "pos": 8, - "end": 14 + "end": 14, + "transformFlags": 0 }, "length": 2, "pos": 1, @@ -406,6 +457,7 @@ module ts { "kind": "JSDocFunctionType", "pos": 1, "end": 11, + "transformFlags": 0, "parameters": { "length": 0, "pos": 10, @@ -420,25 +472,30 @@ module ts { "kind": "JSDocFunctionType", "pos": 1, "end": 26, + "transformFlags": 0, "parameters": { "0": { "kind": "Parameter", "pos": 10, "end": 16, + "transformFlags": 0, "type": { "kind": "StringKeyword", "pos": 10, - "end": 16 + "end": 16, + "transformFlags": 0 } }, "1": { "kind": "Parameter", "pos": 17, "end": 25, + "transformFlags": 0, "type": { "kind": "BooleanKeyword", "pos": 17, - "end": 25 + "end": 25, + "transformFlags": 0 } }, "length": 2, @@ -454,25 +511,30 @@ module ts { "kind": "JSDocFunctionType", "pos": 1, "end": 26, + "transformFlags": 0, "parameters": { "0": { "kind": "Parameter", "pos": 10, "end": 16, + "transformFlags": 0, "type": { "kind": "StringKeyword", "pos": 10, - "end": 16 + "end": 16, + "transformFlags": 0 } }, "1": { "kind": "Parameter", "pos": 17, "end": 25, + "transformFlags": 0, "type": { "kind": "BooleanKeyword", "pos": 17, - "end": 25 + "end": 25, + "transformFlags": 0 } }, "length": 2, @@ -488,24 +550,29 @@ module ts { "kind": "JSDocThisType", "pos": 1, "end": 9, + "transformFlags": 0, "type": { "kind": "JSDocTypeReference", "pos": 6, "end": 9, + "transformFlags": 0, "name": { "kind": "FirstNode", "pos": 6, "end": 9, + "transformFlags": 0, "left": { "kind": "Identifier", "pos": 6, "end": 7, + "transformFlags": 0, "text": "a" }, "right": { "kind": "Identifier", "pos": 8, "end": 9, + "transformFlags": 0, "text": "b" } } @@ -519,24 +586,29 @@ module ts { "kind": "JSDocConstructorType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "JSDocTypeReference", "pos": 5, "end": 8, + "transformFlags": 0, "name": { "kind": "FirstNode", "pos": 5, "end": 8, + "transformFlags": 0, "left": { "kind": "Identifier", "pos": 5, "end": 6, + "transformFlags": 0, "text": "a" }, "right": { "kind": "Identifier", "pos": 7, "end": 8, + "transformFlags": 0, "text": "b" } } @@ -550,10 +622,12 @@ module ts { "kind": "JSDocVariadicType", "pos": 1, "end": 10, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "transformFlags": 0 } }`); }); @@ -564,10 +638,12 @@ module ts { "kind": "JSDocOptionalType", "pos": 1, "end": 8, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 1, - "end": 7 + "end": 7, + "transformFlags": 0 } }`); }); @@ -578,10 +654,12 @@ module ts { "kind": "JSDocOptionalType", "pos": 1, "end": 3, + "transformFlags": 0, "type": { "kind": "JSDocUnknownType", "pos": 1, - "end": 2 + "end": 2, + "transformFlags": 0 } }`); }); @@ -592,17 +670,20 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 11, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" }, "typeArguments": { "0": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "transformFlags": 0 }, "length": 1, "pos": 4, @@ -617,22 +698,26 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 18, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" }, "typeArguments": { "0": { "kind": "NumberKeyword", "pos": 4, - "end": 10 + "end": 10, + "transformFlags": 0 }, "1": { "kind": "StringKeyword", "pos": 11, - "end": 17 + "end": 17, + "transformFlags": 0 }, "length": 2, "pos": 4, @@ -647,20 +732,24 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 11, + "transformFlags": 0, "name": { "kind": "FirstNode", "pos": 1, "end": 11, + "transformFlags": 0, "left": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" }, "right": { "kind": "Identifier", "pos": 3, "end": 11, + "transformFlags": 0, "originalKeywordKind": "FunctionKeyword", "text": "function" } @@ -675,14 +764,17 @@ module ts { "kind": "JSDocArrayType", "pos": 1, "end": 4, + "transformFlags": 0, "elementType": { "kind": "JSDocTypeReference", "pos": 1, "end": 2, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" } } @@ -696,18 +788,22 @@ module ts { "kind": "JSDocArrayType", "pos": 1, "end": 6, + "transformFlags": 0, "elementType": { "kind": "JSDocArrayType", "pos": 1, "end": 4, + "transformFlags": 0, "elementType": { "kind": "JSDocTypeReference", "pos": 1, "end": 2, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" } } @@ -722,22 +818,27 @@ module ts { "kind": "JSDocOptionalType", "pos": 1, "end": 7, + "transformFlags": 0, "type": { "kind": "JSDocArrayType", "pos": 1, "end": 6, + "transformFlags": 0, "elementType": { "kind": "JSDocArrayType", "pos": 1, "end": 4, + "transformFlags": 0, "elementType": { "kind": "JSDocTypeReference", "pos": 1, "end": 2, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 2, + "transformFlags": 0, "text": "a" } } @@ -753,10 +854,12 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 4, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 4, + "transformFlags": 0, "originalKeywordKind": "VarKeyword", "text": "var" } @@ -770,10 +873,12 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 5, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 5, + "transformFlags": 0, "originalKeywordKind": "NullKeyword", "text": "null" } @@ -787,10 +892,12 @@ module ts { "kind": "JSDocTypeReference", "pos": 1, "end": 10, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 1, "end": 10, + "transformFlags": 0, "text": "undefined" } }`); @@ -803,6 +910,7 @@ module ts { "kind": "JSDocTupleType", "pos": 1, "end": 3, + "transformFlags": 0, "types": { "length": 0, "pos": 2, @@ -818,11 +926,13 @@ module ts { "kind": "JSDocTupleType", "pos": 1, "end": 9, + "transformFlags": 0, "types": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 }, "length": 1, "pos": 2, @@ -838,16 +948,19 @@ module ts { "kind": "JSDocTupleType", "pos": 1, "end": 16, + "transformFlags": 0, "types": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 }, "1": { "kind": "StringKeyword", "pos": 9, - "end": 15 + "end": 15, + "transformFlags": 0 }, "length": 2, "pos": 2, @@ -863,21 +976,25 @@ module ts { "kind": "JSDocTupleType", "pos": 1, "end": 24, + "transformFlags": 0, "types": { "0": { "kind": "NumberKeyword", "pos": 2, - "end": 8 + "end": 8, + "transformFlags": 0 }, "1": { "kind": "StringKeyword", "pos": 9, - "end": 15 + "end": 15, + "transformFlags": 0 }, "2": { "kind": "BooleanKeyword", "pos": 16, - "end": 23 + "end": 23, + "transformFlags": 0 }, "length": 3, "pos": 2, @@ -1069,11 +1186,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 27, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1083,16 +1202,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 13, + "transformFlags": 0, "text": "type" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, "end": 22, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 15, - "end": 21 + "end": 21, + "transformFlags": 0 } } }, @@ -1112,11 +1234,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 18, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTypeTag", "pos": 8, "end": 13, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1126,6 +1250,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 13, + "transformFlags": 0, "text": "type" } }, @@ -1145,11 +1270,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 20, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocReturnTag", "pos": 8, "end": 15, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1159,6 +1286,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "transformFlags": 0, "text": "return" } }, @@ -1178,11 +1306,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 27, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1192,16 +1322,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 13, + "transformFlags": 0, "text": "type" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, "end": 22, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 15, - "end": 21 + "end": 21, + "transformFlags": 0 } } }, @@ -1221,11 +1354,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 27, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTypeTag", "pos": 8, "end": 22, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1235,16 +1370,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 13, + "transformFlags": 0, "text": "type" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 14, "end": 22, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 15, - "end": 21 + "end": 21, + "transformFlags": 0 } } }, @@ -1264,11 +1402,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 29, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocReturnTag", "pos": 8, "end": 24, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1278,16 +1418,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "transformFlags": 0, "text": "return" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 16, "end": 24, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 17, - "end": 23 + "end": 23, + "transformFlags": 0 } } }, @@ -1307,11 +1450,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 54, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocReturnTag", "pos": 8, "end": 24, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1321,16 +1466,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 15, + "transformFlags": 0, "text": "return" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 16, "end": 24, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 17, - "end": 23 + "end": 23, + "transformFlags": 0 } } }, @@ -1350,11 +1498,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 30, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocReturnTag", "pos": 8, "end": 25, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1364,16 +1514,19 @@ module ts { "kind": "Identifier", "pos": 9, "end": 16, + "transformFlags": 0, "text": "returns" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 17, "end": 25, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 18, - "end": 24 + "end": 24, + "transformFlags": 0 } } }, @@ -1393,11 +1546,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 34, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1407,22 +1562,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 24, "end": 29, + "transformFlags": 0, "text": "name1" } }, @@ -1443,11 +1602,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 60, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1457,22 +1618,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 24, "end": 29, + "transformFlags": 0, "text": "name1" } }, @@ -1480,6 +1645,7 @@ module ts { "kind": "JSDocParameterTag", "pos": 34, "end": 55, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 34, @@ -1489,22 +1655,26 @@ module ts { "kind": "Identifier", "pos": 35, "end": 40, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 41, "end": 49, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 42, - "end": 48 + "end": 48, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 50, "end": 55, + "transformFlags": 0, "text": "name2" } }, @@ -1524,11 +1694,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 59, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1538,22 +1710,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 24, "end": 29, + "transformFlags": 0, "text": "name1" } }, @@ -1573,11 +1749,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 61, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 30, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1587,22 +1765,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 25, "end": 30, + "transformFlags": 0, "text": "name1" }, "isBracketed": true @@ -1623,11 +1805,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 66, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 31, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1637,22 +1821,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 26, "end": 31, + "transformFlags": 0, "text": "name1" }, "isBracketed": true @@ -1673,11 +1861,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 56, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1687,22 +1877,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, "end": 23, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 16, - "end": 22 + "end": 22, + "transformFlags": 0 } }, "postParameterName": { "kind": "Identifier", "pos": 24, "end": 29, + "transformFlags": 0, "text": "name1" } }, @@ -1722,11 +1916,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 34, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1736,22 +1932,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "preParameterName": { "kind": "Identifier", "pos": 15, "end": 20, + "transformFlags": 0, "text": "name1" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 21, "end": 29, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 22, - "end": 28 + "end": 28, + "transformFlags": 0 } } }, @@ -1771,11 +1971,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 46, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 29, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1785,22 +1987,26 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "preParameterName": { "kind": "Identifier", "pos": 15, "end": 20, + "transformFlags": 0, "text": "name1" }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 21, "end": 29, + "transformFlags": 0, "type": { "kind": "NumberKeyword", "pos": 22, - "end": 28 + "end": 28, + "transformFlags": 0 } } }, @@ -1820,11 +2026,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 24, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 19, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1834,6 +2042,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -1841,10 +2050,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "T" } }, @@ -1869,11 +2080,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 26, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 21, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1883,6 +2096,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -1890,10 +2104,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "K" } }, @@ -1901,10 +2117,12 @@ module ts { "kind": "TypeParameter", "pos": 20, "end": 21, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 20, "end": 21, + "transformFlags": 0, "text": "V" } }, @@ -1929,11 +2147,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 27, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 22, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -1943,6 +2163,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -1950,10 +2171,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "K" } }, @@ -1961,10 +2184,12 @@ module ts { "kind": "TypeParameter", "pos": 21, "end": 22, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 21, "end": 22, + "transformFlags": 0, "text": "V" } }, @@ -1989,11 +2214,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 27, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 22, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -2003,6 +2230,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -2010,10 +2238,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "K" } }, @@ -2021,10 +2251,12 @@ module ts { "kind": "TypeParameter", "pos": 21, "end": 22, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 21, "end": 22, + "transformFlags": 0, "text": "V" } }, @@ -2049,11 +2281,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 28, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 23, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -2063,6 +2297,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -2070,10 +2305,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "K" } }, @@ -2081,10 +2318,12 @@ module ts { "kind": "TypeParameter", "pos": 22, "end": 23, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 22, "end": 23, + "transformFlags": 0, "text": "V" } }, @@ -2109,11 +2348,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 60, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocTemplateTag", "pos": 8, "end": 24, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -2123,6 +2364,7 @@ module ts { "kind": "Identifier", "pos": 9, "end": 17, + "transformFlags": 0, "text": "template" }, "typeParameters": { @@ -2130,10 +2372,12 @@ module ts { "kind": "TypeParameter", "pos": 18, "end": 19, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 18, "end": 19, + "transformFlags": 0, "text": "K" } }, @@ -2141,10 +2385,12 @@ module ts { "kind": "TypeParameter", "pos": 22, "end": 23, + "transformFlags": 0, "name": { "kind": "Identifier", "pos": 22, "end": 23, + "transformFlags": 0, "text": "V" } }, @@ -2169,11 +2415,13 @@ module ts { "kind": "JSDocComment", "pos": 0, "end": 23, + "transformFlags": 0, "tags": { "0": { "kind": "JSDocParameterTag", "pos": 8, "end": 18, + "transformFlags": 0, "atToken": { "kind": "AtToken", "pos": 8, @@ -2183,12 +2431,14 @@ module ts { "kind": "Identifier", "pos": 9, "end": 14, + "transformFlags": 0, "text": "param" }, "preParameterName": { "kind": "Identifier", "pos": 15, "end": 18, + "transformFlags": 0, "text": "foo" } },