From 6235fe828090fe74d1499d7e85d16203fa0948fd Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 9 Oct 2015 15:19:07 -0700 Subject: [PATCH] Cleanup of processTypes script and various transformations. Added JSX --- .vscode/settings.json | 4 + Jakefile.js | 64 +- scripts/processTypes.ts | 1799 ----- scripts/processTypes/discovery.ts | 555 ++ scripts/processTypes/processTypes.ts | 105 + scripts/processTypes/tsconfig.json | 12 + scripts/processTypes/types.ts | 1222 +++ scripts/processTypes/typescript-internal.d.ts | 4 + scripts/processTypes/typescript-internal.js | 1 + scripts/processTypes/utilities.ts | 49 + scripts/typescript-internal.d.ts | 29 - scripts/typescript-internal.js | 1 - src/compiler/binder.ts | 392 +- src/compiler/checker.ts | 98 +- src/compiler/core.ts | 108 +- src/compiler/emitter.ts | 735 +- src/compiler/factory.generated.ts | 6833 ++++++++--------- src/compiler/factory.ts | 140 +- src/compiler/parser.ts | 1 + src/compiler/transform.generated.ts | 569 -- src/compiler/transform.ts | 1416 ++-- src/compiler/transforms/chain.ts | 71 - src/compiler/transforms/es5.ts | 560 -- src/compiler/transforms/es6.ts | 2339 +++--- src/compiler/transforms/jsx.ts | 511 ++ src/compiler/transforms/ts.ts | 1639 ++++ src/compiler/tsc.ts | 8 +- src/compiler/tsconfig.json | 5 +- src/compiler/types.ts | 601 +- src/compiler/utilities.ts | 145 +- src/harness/typeWriter.ts | 4 +- 31 files changed, 10707 insertions(+), 9313 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 scripts/processTypes.ts create mode 100644 scripts/processTypes/discovery.ts create mode 100644 scripts/processTypes/processTypes.ts create mode 100644 scripts/processTypes/tsconfig.json create mode 100644 scripts/processTypes/types.ts create mode 100644 scripts/processTypes/typescript-internal.d.ts create mode 100644 scripts/processTypes/typescript-internal.js create mode 100644 scripts/processTypes/utilities.ts delete mode 100644 scripts/typescript-internal.d.ts delete mode 100644 scripts/typescript-internal.js delete mode 100644 src/compiler/transform.generated.ts delete mode 100644 src/compiler/transforms/chain.ts delete mode 100644 src/compiler/transforms/es5.ts create mode 100644 src/compiler/transforms/jsx.ts create mode 100644 src/compiler/transforms/ts.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..128e7ec0dcc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.trimTrailingWhitespace": true +} \ No newline at end of file diff --git a/Jakefile.js b/Jakefile.js index 6f6c7fecfca..ec575cf61e0 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -17,6 +17,7 @@ var docDirectory = "doc/"; var builtDirectory = "built/"; var builtLocalDirectory = "built/local/"; +var builtScriptsDirectory = "built/scripts/"; var LKGDirectory = "lib/"; var copyright = "CopyrightNotice.txt"; @@ -42,9 +43,9 @@ var compilerSources = [ "binder.ts", "checker.ts", "transform.ts", - "transform.generated.ts", + "transforms/jsx.ts", + "transforms/ts.ts", "transforms/es6.ts", - "transforms/es5.ts", "declarationEmitter.ts", "emitter.ts", "program.ts", @@ -67,9 +68,9 @@ var servicesSources = [ "binder.ts", "checker.ts", "transform.ts", - "transform.generated.ts", + "transforms/jsx.ts", + "transforms/ts.ts", "transforms/es6.ts", - "transforms/es5.ts", "declarationEmitter.ts", "emitter.ts", "program.ts", @@ -247,7 +248,7 @@ function compileFile(outFile, sources, prereqs, opts, callback) { , experimentalTransforms = opts && opts.experimentalTransforms , target = opts && opts.target , diagnostics = opts && opts.diagnostics; - + var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory; var options = "--module commonjs --noImplicitAny --noEmitOnError"; @@ -284,19 +285,19 @@ function compileFile(outFile, sources, prereqs, opts, callback) { if (stripInternal) { options += " --stripInternal"; } - + if (experimentalDecorators) { options += " --experimentalDecorators"; } - + if (experimentalTransforms || (useBuiltCompiler && useTransforms)) { options += " --experimentalTransforms"; } - + if (target) { options += " --target " + target; } - + if (diagnostics) { options += " --diagnostics"; } @@ -390,31 +391,46 @@ desc("Generates a diagnostic file in TypeScript based on an input JSON file"); task("generate-diagnostics", [diagnosticInfoMapTs]); // Generate the node factory -var processTypesJs = path.join(scriptsDirectory, "processTypes.js"); -var processTypesTs = path.join(scriptsDirectory, "processTypes.ts"); +var processTypesBuiltDirectory = path.join(builtScriptsDirectory, "processTypes"); +var processTypesJs = path.join(processTypesBuiltDirectory, "processTypes.js"); +var processTypesDirectory = path.join(scriptsDirectory, "processTypes"); +var processTypesTs = path.join(processTypesDirectory, "processTypes.ts"); +var processTypesSources = [ + "typescript-internal.d.ts", + "processTypes.ts", + "discovery.ts", + "utilities.ts", + "types.ts", +].map(function (f) { + return path.join(processTypesDirectory, f); +}); var typesTs = path.join(compilerDirectory, "types.ts"); var factoryTs = path.join(compilerDirectory, "factory.ts"); -var transformTs = path.join(compilerDirectory, "transform.ts"); var utilitiesTs = path.join(compilerDirectory, "utilities.ts"); var factoryGeneratedTs = path.join(compilerDirectory, "factory.generated.ts"); -var transformGeneratedTs = path.join(compilerDirectory, "transform.generated.ts"); +directory(builtScriptsDirectory); +directory(processTypesBuiltDirectory); file(processTypesTs); // processTypes script -compileFile(processTypesJs, [processTypesTs], [processTypesTs], { +compileFile(processTypesJs, processTypesSources, [processTypesBuiltDirectory].concat(processTypesSources), { useBuiltCompiler: false, noOutFile: true, + outDir: processTypesBuiltDirectory, + target: "es5", experimentalDecorators: true, - target: "es5" +}, function () { + jake.cpR( + path.join(processTypesDirectory, "typescript-internal.js"), + path.join(builtScriptsDirectory, "processTypes/typescript-internal.js")); }); // The generated factory; built for the compiler and for the 'generate-factory' task -file(factoryGeneratedTs, [processTypesJs, typesTs, factoryTs, transformTs, utilitiesTs], function() { - var cmd = "node " + processTypesJs +file(factoryGeneratedTs, [processTypesJs, typesTs, factoryTs, utilitiesTs], function() { + var cmd = "node " + processTypesJs + " " + typesTs + " " + factoryTs - + " " + transformTs + " " + utilitiesTs; console.log(cmd); var ex = jake.createExec([cmd]); @@ -431,10 +447,8 @@ file(factoryGeneratedTs, [processTypesJs, typesTs, factoryTs, transformTs, utili ex.run(); }, { async: true }); -file(transformGeneratedTs, [factoryGeneratedTs]); - desc("Generates a TypeScript file that contains factory methods to create each Syntax Node.") -task("generate-factory", [/*factoryGeneratedTs, transformGeneratedTs*/]); +task("generate-factory", [factoryGeneratedTs]); // Publish nightly @@ -482,7 +496,7 @@ task("publish-nightly", ["configure-nightly", "LKG", "clean", "setDebugMode", "r // Local target to build the compiler and services var tscFile = path.join(builtLocalDirectory, compilerFilename); compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), { - prefixes: [copyright], + prefixes: [copyright], useBuiltCompiler: false }); @@ -516,7 +530,7 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;"; fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents); - // Node package definition file to be distributed without the package. Created by replacing + // Node package definition file to be distributed without the package. Created by replacing // 'ts' namespace with '"typescript"' as a module. var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"'); fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents); @@ -524,7 +538,7 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc var serverFile = path.join(builtLocalDirectory, "tsserver.js"); compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), { - prefixes: [copyright], + prefixes: [copyright], useBuiltCompiler: true }); @@ -746,7 +760,7 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () { var nodeServerOutFile = 'tests/webTestServer.js'; var nodeServerInFile = 'tests/webTestServer.ts'; compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], { - useBuiltCompiler: true, + useBuiltCompiler: true, noOutFile: true }); diff --git a/scripts/processTypes.ts b/scripts/processTypes.ts deleted file mode 100644 index b01b0193590..00000000000 --- a/scripts/processTypes.ts +++ /dev/null @@ -1,1799 +0,0 @@ -import { - sys, - getDefaultCompilerOptions, - createProgram, - createCompilerHost, - forEachChild, - getLeadingCommentRanges, - computeLineStarts, - createTextWriter, - combinePaths, - getNodeId, - getSymbolId, - getProperty, - hasProperty, - createSourceFile, - map, - SyntaxKind, - CompilerOptions, - CompilerHost, - Program, - TypeChecker, - CommentRange, - EmitTextWriter, - Node, - SourceFile, - Declaration, - ModuleDeclaration, - ModuleBlock, - InterfaceDeclaration, - TypeAliasDeclaration, - EnumDeclaration, - EnumMember, - PropertyDeclaration, - TypeNode, - TypeReferenceNode, - UnionTypeNode, - ExpressionWithTypeArguments, - ExpressionStatement, - Expression, - CallExpression, - PropertyAccessExpression, - ObjectLiteralExpression, - ArrayLiteralExpression, - PropertyAssignment, - LiteralExpression, - Identifier, - SymbolFlags, - Symbol, - SymbolTable, - TypeFlags, - Type, - TypeReference, - InterfaceType, - Map, -} from "./typescript-internal"; - -interface SyntaxNode { - kind?: SyntaxKind; - kindName?: string; - typeName?: string; - members?: SyntaxMember[]; - options?: KindOptions; -} - -interface SyntaxMember { - paramName?: string; - propertyName?: string; - typeName?: string; - elementTypeName?: string; - visitorFunction?: string; - isFactoryParam?: boolean; - isNode?: boolean; - isNodeArray?: boolean; - isModifiersArray?: boolean; - startsNewLexicalEnvironment?: boolean; -} - -interface EnumValue { - symbol: Symbol; - value: T; -} - -const enum FactoryHiddenState { - None, - Hidden, - Visible -} - -interface KindOptions { - create: boolean | string; - update: boolean | string; - test: boolean | string; -} - -const columnWrap = 150; -const emptyArray: any[] = []; -const annotationPattern = /@(\w+\s*[^\r\n]*)/g; - -let options: CompilerOptions; -let host: CompilerHost; -let program: Program; -let checker: TypeChecker; -let typesSourceFile: SourceFile; -let factorySourceFile: SourceFile; -let transformSourceFile: SourceFile; -let utilitiesSourceFile: SourceFile; -let tsModuleSymbol: Symbol; -let nodeSymbol: Symbol; -let nodeArraySymbol: Symbol; -let modifiersArraySymbol: Symbol; -let syntaxKindSymbol: Symbol; -let syntaxNodes: SyntaxNode[] = []; - -let annotationConstructors: Map = {}; - -/** - * A one-to-many map of one Symbol to the many Annotations that are attached to its declarations. - */ -let symbolToAnnotations: Annotation[][] = []; - -/** - * A one-to-many map of one node type Symbol to the many SyntaxKind Symbols it directly describes. - */ -let typeToSyntaxKinds: Symbol[][] = []; - -/** - * A one-to-one map of one SyntaxKind Symbol to the one node type Symbol that directly describes it. - */ -let syntaxKindToType: Symbol[] = []; - -let syntaxKindToSyntaxNode: SyntaxNode[] = []; - -let nodeArrayTypeUsages: Map = {}; - -let superTypeSymbolsForTypeSymbol: Symbol[][] = []; -let ancestorTypeSymbolsForTypeSymbol: Symbol[][] = []; -let descendantTypeSymbolsForTypeSymbol: Symbol[][] = []; -let descendantSyntaxKindSymbolsForTypeSymbol: Symbol[][] = []; -let typeSymbolsById: Symbol[] = []; - -let syntaxKindTypeUsages: Map = {}; -let memberTypeUsages: Map = {}; -let memberTypeUsageRedirects: Map = {}; - -function main() { - if (sys.args.length < 3) { - sys.write("Usage:" + sys.newLine) - sys.write("\tnode processTypes.js " + sys.newLine); - return; - } - - options = getCompilerOptions(); - host = createCompilerHost(options); - - let typesTsFileName = host.getCanonicalFileName(sys.resolvePath(sys.args[0])); - let factoryTsFileName = host.getCanonicalFileName(sys.resolvePath(sys.args[1])); - let transformTsFileName = host.getCanonicalFileName(sys.resolvePath(sys.args[2])); - let utilitiesTsFileName = host.getCanonicalFileName(sys.resolvePath(sys.args[3])); - program = createProgram([typesTsFileName, factoryTsFileName, transformTsFileName, utilitiesTsFileName], options, host); - checker = program.getTypeChecker(); - - typesSourceFile = program.getSourceFile(typesTsFileName); - factorySourceFile = program.getSourceFile(factoryTsFileName); - transformSourceFile = program.getSourceFile(transformTsFileName); - utilitiesSourceFile = program.getSourceFile(utilitiesTsFileName); - - // Resolve common symbols - tsModuleSymbol = resolveQualifiedName(typesSourceFile, "ts", SymbolFlags.Module); - nodeSymbol = resolveQualifiedName(typesSourceFile, "ts.Node", SymbolFlags.Type); - nodeArraySymbol = resolveQualifiedName(typesSourceFile, "ts.NodeArray", SymbolFlags.Type); - modifiersArraySymbol = resolveQualifiedName(typesSourceFile, "ts.ModifiersArray", SymbolFlags.Type); - syntaxKindSymbol = resolveQualifiedName(typesSourceFile, "ts.SyntaxKind", SymbolFlags.Enum); - - discover(); - - let factoryDirectory = sys.resolvePath(combinePaths(factoryTsFileName, "..")); - let factoryOutputFile = combinePaths(factoryDirectory, "factory.generated.ts"); - generateFactory(factoryOutputFile); - - let transformDirectory = sys.resolvePath(combinePaths(transformTsFileName, "..")); - let transformOutputFile = combinePaths(transformDirectory, "transform.generated.ts"); - generateTransform(transformOutputFile); -} - -/** - * Discovers type information and symbols for various SyntaxNodes - */ -function discover() { - - // Discover each interface and type alias - let typeSymbols = getSymbols(tsModuleSymbol.exports, SymbolFlags.Interface | SymbolFlags.TypeAlias); - for (let typeSymbol of typeSymbols) { - let kindAnnotations = findAllAnnotations(typeSymbol, KindAnnotation.match); - if (kindAnnotations.length) { - discoverSyntaxNodes(typeSymbol, kindAnnotations); - } - } - - // Sort the syntax nodes by SyntaxKind - syntaxNodes.sort((a, b) => { - return a.kind - b.kind; - }); - - // Set up member type usage redirects for types with a single kind - for (let typeName in syntaxKindTypeUsages) { - if (syntaxKindTypeUsages[typeName].length === 1) { - memberTypeUsageRedirects[typeName] = syntaxKindTypeUsages[typeName][0].name; - } - } - - function discoverTypeHierarchy(typeSymbol: Symbol) { - discoverTypeHierarchyWorker(typeSymbol, /*ancestorOrSelfTypeSymbol*/ typeSymbol); - } - - function discoverTypeHierarchyWorker(typeSymbol: Symbol, ancestorOrSelfTypeSymbol: Symbol) { - let superTypeSymbols = getSuperTypeSymbols(ancestorOrSelfTypeSymbol); - for (let ancestorTypeSymbol of superTypeSymbols) { - let descendantTypeSymbols = descendantTypeSymbolsForTypeSymbol[getSymbolId(ancestorTypeSymbol)]; - if (!descendantTypeSymbols) { - descendantTypeSymbols = descendantTypeSymbolsForTypeSymbol[getSymbolId(ancestorTypeSymbol)] = []; - discoverTypeHierarchyWorker(ancestorTypeSymbol, /*ancestorOrSelfTypeSymbol*/ ancestorTypeSymbol); - } - if (descendantTypeSymbols.indexOf(typeSymbol) === -1) { - descendantTypeSymbols.push(typeSymbol); - } - } - } - - /** - * Discovers syntax nodes associated with a type and one or more syntax kinds. - */ - function discoverSyntaxNodes(typeSymbol: Symbol, kindAnnotations: KindAnnotation[]) { - // Skip this node if it is marked with @factoryhidden(true) - if (getFactoryHiddenStateForSymbol(typeSymbol) === FactoryHiddenState.Hidden) { - return; - } - - getSuperTypeSymbols(typeSymbol, /*flattenHierarchy*/ true); - - let symbolOrder: string[]; - for (let kindAnnotation of kindAnnotations) { - let kind = kindAnnotation.kind; - let kindSymbol = kindAnnotation.kindSymbol; - let type = checker.getDeclaredTypeOfSymbol(typeSymbol); - - recordTypeToSyntaxKindRelationships(typeSymbol, kindSymbol); - - // Discover the members of the node type - var members: SyntaxMember[] = []; - for (let property of checker.getPropertiesOfType(type)) { - // Skip any hidden properties - if (getFactoryHiddenStateForProperty(typeSymbol, property.name) === FactoryHiddenState.Hidden) { - continue; - } - - let visitorAnnotation = findFirstAnnotation(property, MemberVisitorAnnotation.match); - let visitorFunction = visitorAnnotation ? visitorAnnotation.functionName : undefined; - - // Collect information about the type - let typeNode = getTypeNodeForProperty(property); - let propertyIsFactoryParam = isFactoryParamProperty(typeSymbol, property.name); - let propertyIsNode = typeNode && isSubtypeOf(typeNode, nodeSymbol); - let propertyIsNodeArray = typeNode && isNodeArray(typeNode); - let propertyIsModifiersArray = typeNode && isModifiersArray(typeNode); - if (propertyIsFactoryParam || propertyIsNodeArray || propertyIsModifiersArray || propertyIsNode) { - let typeName = typeNode ? normalizeTypeName(typeNode.getText()) : "any"; - let elementTypeName = - propertyIsNodeArray ? normalizeTypeName((typeNode).typeArguments[0].getText()) : - propertyIsModifiersArray ? "Modifier" : - undefined; - - let propertyStartsNewLexicalEnvironment = propertyIsNode && startsNewLexicalEnvironment(property); - - members.push({ - propertyName: property.name, - paramName: property.name === "arguments" ? "_arguments" : property.name, - typeName: typeName, - elementTypeName: elementTypeName, - visitorFunction: visitorFunction, - isFactoryParam: propertyIsFactoryParam, - isNodeArray: propertyIsNodeArray, - isModifiersArray: propertyIsModifiersArray, - isNode: propertyIsNode, - startsNewLexicalEnvironment: propertyStartsNewLexicalEnvironment - }); - - if (!propertyIsFactoryParam) { - let typeNames = splitTypeName(propertyIsNode ? typeName : elementTypeName); - for (let typeName of typeNames) { - let typeSymbol = getSymbol(tsModuleSymbol.exports, typeName, SymbolFlags.Type); - if (typeSymbol) { - getSuperTypeSymbols(typeSymbol, /*flattenHierarchy*/ true); - } - } - - recordTypeUsageForMember(propertyIsNode ? typeName : elementTypeName); - } - - if (elementTypeName) { - nodeArrayTypeUsages[elementTypeName] = true; - } - } - } - - // Sort the members of the type in the correct order for create and update methods - let kindOrder = getFactoryOrder(kindSymbol, /*inherited*/ false); - var overrides = kindOrder || symbolOrder || (symbolOrder = getFactoryOrder(typeSymbol, /*inherited*/ true)); - if (overrides) { - let indices = members.map((_, i) => i); - indices.sort((a, b) => { - let aOverride = overrides.indexOf(members[a].propertyName); - let bOverride = overrides.indexOf(members[b].propertyName); - if (aOverride >= 0) { - if (bOverride >= 0) { - return aOverride - bOverride; - } - - return -1; - } - else if (bOverride >= 0) { - return +1; - } - - return a - b; - }); - - members = indices.map(i => members[i]); - } - - // Add the syntax node - let syntaxNode: SyntaxNode = { - kind, - kindName: kindSymbol.name, - typeName: typeSymbol.name, - members, - options: kindAnnotation.options - }; - - syntaxNodes.push(syntaxNode); - syntaxKindToSyntaxNode[getSymbolId(kindSymbol)] = syntaxNode; - } - } - - /** - * Records the various relationships between a node type Symbol and a SyntaxKind symbol. - */ - function recordTypeToSyntaxKindRelationships(typeSymbol: Symbol, kindSymbol: Symbol): void { - // Add the SyntaxKind Symbol to the set of SyntaxKind Symbols for the node type Symbol. - // NOTE: This could also be retrieved by reading its @kind annotations. - let syntaxKindsForType = getSyntaxKindSymbolsForTypeSymbol(typeSymbol, /*ensureExists*/ true); - if (syntaxKindsForType.indexOf(kindSymbol) === -1) { - syntaxKindsForType.push(kindSymbol); - } - - // Set the node type Symbol for this SyntaxKind Symbol - syntaxKindToType[getSymbolId(kindSymbol)] = typeSymbol; - - // Record the supertypes associated with this SyntaxKind Symbol - recordTypeUsagesForKind(kindSymbol, typeSymbol); - } - - function recordTypeUsagesForKind(kindSymbol: Symbol, typeSymbol: Symbol) { - //memberTypeUsages[kindSymbol.name] = false; - recordTypeUsagesForKindWorker(kindSymbol, typeSymbol); - } - - function recordTypeUsagesForKindWorker(kindSymbol: Symbol, typeSymbol: Symbol) { - let usages = syntaxKindTypeUsages[typeSymbol.name]; - if (!usages) { - syntaxKindTypeUsages[typeSymbol.name] = usages = []; - } - - if (usages.indexOf(kindSymbol) === -1) { - usages.push(kindSymbol); - } - - for (let superType of getSuperTypeSymbols(typeSymbol)) { - recordTypeUsagesForKindWorker(kindSymbol, superType); - } - } - - function recordTypeUsageForMember(typeName: string) { - if (!hasProperty(memberTypeUsages, typeName)) { - memberTypeUsages[typeName] = true; - } - } - - function normalizeTypeName(typeName: string) { - let parts = typeName.split(/\s*\|\s*/g); - if (parts.length === 0) { - return parts[0]; - } - - parts.sort(); - return parts.join(" | "); - } - - function getTypeNodeForProperty(property: Symbol) { - return (property.declarations[0]).type; - } -} - -function generateFactory(outputFile: string) { - let writer = createLineWrappingTextWriter(host.getNewLine(), columnWrap); - writer.write(`// `); - writer.writeLine(); - writer.write(`/// `); - writer.writeLine(); - writer.write(`namespace ts {`); - writer.writeLine(); - // writer.increaseIndent(); - // writer.write(`export namespace factory {`); - // writer.writeLine(); - writer.increaseIndent(); - writeCreateAndUpdateFunctions(); - writeCloneFunction(); - // writer.decreaseIndent(); - // writer.write(`}`); - // writer.writeLine(); - writeIsNodeFunctions(); - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - sys.writeFile(outputFile, writer.getText()); - - function writeCreateAndUpdateFunctions() { - for (let syntaxNode of syntaxNodes) { - writeCreateFunction(syntaxNode); - writeUpdateFunction(syntaxNode); - } - } - - function writeIsNodeFunctions() { - for (let syntaxNode of syntaxNodes) { - writeIsNodeFunction(syntaxNode); - } - - for (let typeName in memberTypeUsages) { - if (getProperty(memberTypeUsages, typeName) && !hasProperty(memberTypeUsageRedirects, typeName)) { - writeIsAnyNodeFunction(typeName); - } - } - } - - function writeCreateFunction(syntaxNode: SyntaxNode) { - if (!syntaxNode.options.create) { - return; - } - - let createFunctionName = getCreateFunctionName(syntaxNode); - - // Skip the create function for this node if it is already defined in factory.ts - if (resolveQualifiedName(factorySourceFile, `ts.${createFunctionName}`, SymbolFlags.Function)) { - return; - } - - writer.write(`export function ${createFunctionName}(`); - - for (let member of syntaxNode.members) { - let type = - member.isNodeArray ? `Array<${member.elementTypeName}>` : - member.isModifiersArray ? `Array` : - member.typeName; - - writer.write(`${member.paramName}?: ${type}, `); - } - - writer.write(`location?: TextRange, flags?: NodeFlags): ${syntaxNode.typeName} {`); - writer.writeLine(); - - writer.increaseIndent(); - if (syntaxNode.members.length) { - writer.write(`let node = createNode<${syntaxNode.typeName}>(SyntaxKind.${syntaxNode.kindName}, location, flags);`); - writer.writeLine(); - if (syntaxNode.members.length > 1) { - writer.write(`if (`); - - let first = true; - for (let member of syntaxNode.members) { - if (first) { - first = false; - } - else { - writer.write(` || `); - } - - writer.write(member.paramName); - } - writer.write(`) {`); - writer.writeLine(); - writer.increaseIndent(); - } - - for (let member of syntaxNode.members) { - if (member.isModifiersArray) { - writer.write(`setModifiers(node, modifiers);`); - } - else if (member.isNodeArray) { - writer.write(`node.${member.propertyName} = ${member.paramName} && createNodeArray(${member.paramName})`); - } - else { - writer.write(`node.${member.propertyName} = ${member.paramName};`); - } - - writer.writeLine(); - } - - if (syntaxNode.members.length > 1) { - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - - writer.write(`return node;`); - writer.writeLine(); - } - else { - writer.write(`return createNode<${syntaxNode.typeName}>(SyntaxKind.${syntaxNode.kindName}, location, flags);`); - writer.writeLine(); - } - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - - function writeUpdateFunction(syntaxNode: SyntaxNode) { - if (!syntaxNode.options.update || !hasChildNodes(syntaxNode)) { - return; - } - - let createFunctionName = getCreateFunctionName(syntaxNode); - let updateFunctionName = getUpdateFunctionName(syntaxNode); - - // Skip the update function for this node if it is defined in factory.ts - if (resolveQualifiedName(factorySourceFile, `ts.${updateFunctionName}`, SymbolFlags.Function)) { - return; - } - - writer.write(`export function ${updateFunctionName}(node: ${syntaxNode.typeName}`); - - for (let i = 0; i < syntaxNode.members.length; ++i) { - let member = syntaxNode.members[i]; - if (member.isFactoryParam) { - continue; - } - - - let type = - member.isNodeArray ? `Array<${member.elementTypeName}>` : - member.isModifiersArray ? `Array` : - member.typeName; - - writer.write(`, ${member.paramName}: ${type}`); - } - - writer.write(`): ${syntaxNode.typeName} {`); - writer.writeLine(); - - writer.increaseIndent(); - - writer.write(`if (`); - let first = true; - for (let member of syntaxNode.members) { - if (member.isFactoryParam) { - continue; - } - - if (first) { - first = false; - } - else { - writer.write(` || `); - } - - writer.write(`${member.paramName} !== node.${member.propertyName}`); - } - - - writer.write(`) {`); - writer.writeLine(); - - writer.increaseIndent(); - - writer.write(`let newNode = ${createFunctionName}(`); - - for (let i = 0; i < syntaxNode.members.length; ++i) { - if (i > 0) { - writer.write(`, `); - } - - let member = syntaxNode.members[i]; - if (member.isFactoryParam) { - writer.write(`node.${member.propertyName}`); - } - else { - writer.write(member.paramName); - } - } - - writer.write(`);`); - writer.writeLine(); - - writer.write(`return updateFrom(node, newNode);`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.write(`return node;`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - - function writeIsNodeFunction(syntaxNode: SyntaxNode) { - if (syntaxNode.typeName === "Node") { - return; - } - - if (!syntaxNode.options.test) { - return; - } - - // Skip the is function for this node if it is already defined - if (resolveQualifiedName(factorySourceFile, `ts.is${syntaxNode.kindName}`, SymbolFlags.Function)) { - return; - } - - writer.write(`export function is${syntaxNode.kindName}(node: Node): node is ${syntaxNode.typeName} {`); - writer.writeLine(); - writer.increaseIndent(); - writer.write(`return node && node.kind === SyntaxKind.${syntaxNode.kindName};`); - writer.writeLine(); - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - - function writeIsAnyNodeFunction(typeName: string) { - if (typeName === "Node") { - return; - } - - let typeNames = splitTypeName(typeName); - let nodeTestFunction: string; - if (typeNames.length === 1) { - let typeSymbol = resolveExportedQualifiedName(tsModuleSymbol, typeName, SymbolFlags.Type); - if (typeSymbol) { - let nodeTestAnnotation = findFirstAnnotation(typeSymbol, NodeTestAnnotation.match); - if (nodeTestAnnotation) { - nodeTestFunction = nodeTestAnnotation.functionName; - } - } - } - - if (!nodeTestFunction) { - nodeTestFunction = `is${typeNameToMethodNameSuffix(typeName)}`; - } - - // Skip the is function for this type if it is already defined in factory.ts - if (resolveQualifiedName(factorySourceFile, `ts.${nodeTestFunction}`, SymbolFlags.Function)) { - return; - } - - // Skip the is function for this type if has the same name as a SyntaxKind - if (getSymbol(syntaxKindSymbol.exports, typeName, SymbolFlags.EnumMember)) { - return; - } - - writer.write(`export function ${nodeTestFunction}(node: Node): node is ${typeName} {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`if (node) {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`switch (node.kind) {`); - writer.writeLine(); - writer.increaseIndent(); - - let kinds = getDescendantSyntaxKindSymbolsForTypeName(typeName); - for (let kind of kinds) { - writer.write(`case SyntaxKind.${kind.name}:`); - writer.writeLine(); - } - - if (kinds.length > 0) { - writer.increaseIndent(); - writer.write(`return true;`); - writer.writeLine(); - writer.decreaseIndent(); - } - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.write(`return false; `); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - - function writeCloneFunction() { - writer.write(`export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode;`); - writer.writeLine(); - - writer.write(`export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`if (!node) {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`return node;`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.write(`switch (node.kind) {`); - writer.writeLine(); - writer.increaseIndent(); - - for (let syntaxNode of syntaxNodes) { - if (!syntaxNode.options.create) { - continue; - } - - let createFunctionName = getCreateFunctionName(syntaxNode); - - writer.write(`case SyntaxKind.${syntaxNode.kindName}:`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`return ${createFunctionName}(`); - for (let member of syntaxNode.members) { - writer.write(`(<${syntaxNode.typeName}>node).${member.propertyName}, `); - } - - writer.write(`location, flags);`); - writer.writeLine(); - - writer.decreaseIndent(); - } - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - } - -} - -function generateTransform(outputFile: string) { - let writer = createTextWriter(host.getNewLine()); - writer.write(`// `); - writer.writeLine(); - writer.write(`/// `); - writer.writeLine(); - writer.write(`/// `); - writer.writeLine(); - writer.write(`/* @internal */`); - writer.writeLine(); - writer.write(`namespace ts {`); - writer.writeLine(); - writer.increaseIndent(); - writeAcceptFunction(); - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - sys.writeFile(outputFile, writer.getText()); - - function writeAcceptFunction() { - writer.write(`export function accept(transformer: Transformer, node: Node, pipeline: Pipeline, write: PipelineOutput): void {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`if (!node) {`); - writer.writeLine(); - writer.increaseIndent(); - - writer.write(`return;`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.write(`let { visitNode, visitNodes } = transformer;`); - writer.writeLine(); - - writer.write(`switch (node.kind) {`); - writer.writeLine(); - writer.increaseIndent(); - - for (let syntaxNode of syntaxNodes) { - if (!hasChildNodes(syntaxNode) || syntaxNode.kindName === "SourceFile") { - continue; - } - - writer.write(`case SyntaxKind.${syntaxNode.kindName}:`); - writer.writeLine(); - writer.increaseIndent(); - - let updateFunctionName = getUpdateFunctionName(syntaxNode); - - writer.write(`return write(${updateFunctionName}(`); - writer.increaseIndent(); - writer.write(`<${syntaxNode.typeName}>node`); - - for (let member of syntaxNode.members) { - if (member.isFactoryParam) { - continue; - } - - writer.write(`, `); - writer.writeLine(); - - if (member.typeName === "Node") { - writer.write(`(<${syntaxNode.typeName}>node).${member.propertyName}`); - } - else { - let isStatement = member.typeName === "Statement"; - let visitorFunction = - member.visitorFunction ? member.visitorFunction : - member.isNodeArray || member.isModifiersArray ? `visitNodes` : - `visitNode`; - - writer.write(`${visitorFunction}(`); - if (member.visitorFunction) { - writer.write(`transformer, `); - } - - writer.write(`(<${syntaxNode.typeName}>node).${member.propertyName}, pipeline`); - - if (isStatement) { - writer.write(`, PipelineFlags.StatementOrBlock`); - } - else if (member.startsNewLexicalEnvironment) { - writer.write(`, PipelineFlags.LexicalEnvironment`); - } - - writer.write(`)`); - } - } - - writer.write(`));`); - writer.writeLine(); - writer.decreaseIndent(); - writer.decreaseIndent(); - } - - writer.write(`default:`); - writer.writeLine(); - writer.increaseIndent(); - writer.write(`return write(node);`); - writer.writeLine(); - writer.decreaseIndent(); - writer.decreaseIndent(); - writer.write(`}`); - writer.writeLine(); - - writer.decreaseIndent(); - writer.write('}'); - writer.writeLine(); - } -} - -// -// Utilities -// - -function splitTypeName(typeName: string) { - return typeName.split(/\s*\|\s*/g); -} - -function typeNameToMethodNameSuffix(typeName: string) { - let typeNames = splitTypeName(typeName); - typeNames = typeNames.map(typeNameToSyntaxKindOrTypeName); - return typeNames.join("Or"); -} - -function typeNameToSyntaxKindOrTypeName(typeName: string) { - let typeSymbol = getSymbol(tsModuleSymbol.exports, typeName, SymbolFlags.Type); - let syntaxKindSymbols = getDescendantSyntaxKindSymbolsForTypeSymbol(typeSymbol); - if (syntaxKindSymbols && syntaxKindSymbols.length === 1) { - return syntaxKindSymbols[0].name; - } - return typeName; -} - -function fillKindsForType(typeSymbol: Symbol, kinds: Symbol[]) { - let usages = getProperty(syntaxKindTypeUsages, typeSymbol.name); - if (usages) { - for (let usage of usages) { - if (kinds.indexOf(usage) === -1) { - kinds.push(usage); - } - } - } - else if (typeSymbol.declarations[0].kind === SyntaxKind.TypeAliasDeclaration) { - for (let superType of getSuperTypeSymbols(typeSymbol)) { - fillKindsForType(superType, kinds); - } - } -} - -/** - * Resolves a symbol with the specified name and meaning starting at the provided location. - * @param location The node at which to resolve the name. - * @param name The name of a symbol to resolve. - * @param meaning The meaning of the symbol. - */ -function resolveName(location: Node, name: string, meaning: SymbolFlags): Symbol { - let symbols = checker.getSymbolsInScope(location, meaning); - for (let symbol of symbols) { - if (symbol.name === name) { - return symbol; - } - } - - return undefined; -} - -/** - * Gets a symbol with the specified name and meaning from the provided symbol table. - * @param symbols The symbol table from which to retrieve a named symbol. - * @param name The name of the symbol to retrieve. - * @param meaning The meaning of the symbol. - */ -function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol { - if (symbols && meaning && hasProperty(symbols, name)) { - let symbol = symbols[name]; - if (symbol.flags & meaning) { - return symbol; - } - } - - return undefined; -} - -/** - * Gets al symbols with the specified meaning from the provided symbol table. - * @param symbols The symbol table from which to retrieve symbols. - * @param meaning The meaning of each symbol. - */ -function getSymbols(symbols: SymbolTable, meaning: SymbolFlags): Symbol[] { - let results: Symbol[]; - if (symbols && meaning) { - for (let name in symbols) { - let symbol = getProperty(symbols, name); - if (symbol && symbol.flags & meaning) { - if (!results) { - results = []; - } - - results.push(symbol); - } - } - } - - return results || emptyArray; -} - -/** - * Resolves a symbol with the specified fully qualified name and meaning starting at the provided location. - * @param location The node at which to resolve the name. - * @param name A dot-seperated name for the symbol to retrieve. - * @param meaning The meaning of the symbol. - */ -function resolveQualifiedName(location: Node, name: string, meaning: SymbolFlags): Symbol { - return resolveQualifiedNameParts(location, name.split("."), meaning); -} - -function resolveExportedQualifiedName(symbol: Symbol, name: string, meaning: SymbolFlags): Symbol { - return resolveExportedQualifiedNameParts(symbol, name.split("."), meaning); -} - -function resolveExportedQualifiedNameParts(symbol: Symbol, qn: string[], meaning: SymbolFlags): Symbol { - if (qn.length === 1) { - return getSymbol(symbol.exports, qn[0], meaning); - } - - let namespace = getSymbol(symbol.exports, qn[0], SymbolFlags.Namespace); - if (namespace === undefined) { - return undefined; - } - - for (let i = 1; i < qn.length - 1; i++) { - namespace = getSymbol(namespace.exports, qn[i], SymbolFlags.Namespace); - if (namespace === undefined) { - return undefined; - } - } - - return getSymbol(namespace.exports, qn[qn.length - 1], meaning); -} - -/** - * Resolves a symbol with the specified fully qualified name and meaning starting at the provided location. - * @param location The node at which to resolve the name. - * @param qn An array of qualified name segments. - * @param meaning The meaning of the symbol. - */ -function resolveQualifiedNameParts(location: Node, qn: string[], meaning: SymbolFlags): Symbol { - if (qn.length === 1) { - return resolveName(location, qn[0], meaning); - } - - let namespace = resolveName(location, qn[0], SymbolFlags.Namespace); - if (namespace === undefined) { - return undefined; - } - - for (let i = 1; i < qn.length - 1; i++) { - namespace = getSymbol(namespace.exports, qn[i], SymbolFlags.Namespace); - if (namespace === undefined) { - return undefined; - } - } - - return getSymbol(namespace.exports, qn[qn.length - 1], meaning); -} - -/** - * Gets the value of the specified enum. - * @param location The node at which to resolve the name. - * @param name The name of the enum member. - */ -function getEnumLiteralValue(location: Node, name: string): EnumValue { - let qn = name.split("."); - if (qn.length === 1) { - return undefined; - } - - let container = resolveQualifiedNameParts(location, qn.slice(0, qn.length - 1), SymbolFlags.Enum); - if (!container) { - return undefined; - } - - let symbol = getSymbol(container.exports, qn[qn.length - 1], SymbolFlags.EnumMember); - if (!symbol) { - return undefined; - } - - let value = checker.getConstantValue(symbol.declarations[0]); - return { symbol, value }; -} - -function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string { - return symbol ? checker.symbolToString(symbol, enclosingDeclaration, meaning) : undefined; -} - -function hasChildNodes(syntaxNode: SyntaxNode) { - for (let member of syntaxNode.members) { - if (member.isFactoryParam) { - continue; - } - - if (member.isNode || member.isNodeArray || member.isModifiersArray) { - return true; - } - } - - return false; -} - -function isTypeReferenceNode(node: Node): node is TypeReferenceNode { - return node ? node.kind === SyntaxKind.TypeReference : false; -} - -function isUnionTypeNode(node: Node): node is UnionTypeNode { - return node ? node.kind === SyntaxKind.UnionType : false; -} - -function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { - return node ? node.kind === SyntaxKind.InterfaceDeclaration : false; -} - -function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { - return node ? node.kind === SyntaxKind.TypeAliasDeclaration : false; -} - -function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { - return node ? node.kind === SyntaxKind.ExpressionWithTypeArguments : false; -} - -function isNodeArray(typeNode: TypeNode): boolean { - return isTypeReferenceNode(typeNode) ? checker.getSymbolAtLocation(typeNode.typeName) === nodeArraySymbol : false; -} - -function isModifiersArray(typeNode: TypeNode): boolean { - return isTypeReferenceNode(typeNode) ? checker.getSymbolAtLocation(typeNode.typeName) === modifiersArraySymbol : false; -} - -function isPropertyAssignment(node: Node): node is PropertyAssignment { - return node && node.kind === SyntaxKind.PropertyAssignment; -} - -function isIdentifier(node: Node): node is Identifier { - return node && node.kind === SyntaxKind.Identifier; -} - -function isSubtypeOf(node: TypeNode | Declaration, superTypeSymbol: Symbol): boolean { - if (isInterfaceDeclaration(node)) { - if (node.heritageClauses) { - for (let superType of node.heritageClauses[0].types) { - if (isSubtypeOf(superType, superTypeSymbol)) { - return true; - } - } - } - } - else if (isTypeAliasDeclaration(node)) { - return isSubtypeOf(node.type, superTypeSymbol); - } - else if (isUnionTypeNode(node)) { - for (let constituentType of node.types) { - if (isSubtypeOf(constituentType, superTypeSymbol)) { - return true; - } - } - } - else { - let typeSymbol = isTypeReferenceNode(node) ? checker.getSymbolAtLocation(node.typeName) - : isExpressionWithTypeArguments(node) ? checker.getSymbolAtLocation(node.expression) - : undefined; - - if (!typeSymbol) { - return false; - } - else if (typeSymbol === superTypeSymbol) { - return true; - } - - return isSubtypeOf(typeSymbol.declarations[0], superTypeSymbol); - } - - return false; -} - -function getSuperTypeSymbols(typeSymbol: Symbol, flattenHierarchy?: boolean) { - if (flattenHierarchy) { - let superTypeSymbolsFlat = ancestorTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)]; - if (superTypeSymbolsFlat) { - return superTypeSymbolsFlat; - } - - superTypeSymbolsFlat = []; - - let superTypeSymbols = getSuperTypeSymbols(typeSymbol, /*flattenHierarchy*/ false).slice(0); - for (let superTypeSymbol of superTypeSymbols) { - if (superTypeSymbolsFlat.indexOf(superTypeSymbol) !== -1) { - continue; - } - - superTypeSymbolsFlat.push(superTypeSymbol); - if (superTypeSymbol === nodeSymbol) { - continue; - } - - let ancestorTypeSymbols = getSuperTypeSymbols(superTypeSymbol, /*flattenHierarch*/ true); - for (let ancestorTypeSymbol of ancestorTypeSymbols) { - if (superTypeSymbolsFlat.indexOf(ancestorTypeSymbol) === -1) { - superTypeSymbolsFlat.push(ancestorTypeSymbol); - } - } - } - - return ancestorTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)] = superTypeSymbolsFlat; - } - else { - let superTypeSymbols = superTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)]; - if (superTypeSymbols) { - return superTypeSymbols; - } - - superTypeSymbols = []; - - typeSymbolsById[getSymbolId(typeSymbol)] = typeSymbol; - - let decl = typeSymbol.declarations[0]; - if (isTypeAliasDeclaration(decl)) { - fillSuperTypes(decl.type, superTypeSymbols); - } - else if (isInterfaceDeclaration(decl) && decl.heritageClauses) { - for (let superType of decl.heritageClauses[0].types) { - fillSuperTypes(superType, superTypeSymbols); - } - } - - return superTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)] = superTypeSymbols; - } -} - -function fillSuperTypes(node: TypeNode, superTypeSymbols: Symbol[]) { - if (isUnionTypeNode(node)) { - // Flatten union types - for (let constituentType of node.types) { - fillSuperTypes(constituentType, superTypeSymbols); - } - } - else { - // Add type references - let symbol = - isTypeReferenceNode(node) ? checker.getSymbolAtLocation(node.typeName) : - isExpressionWithTypeArguments(node) ? checker.getSymbolAtLocation(node.expression) : - undefined; - - if (symbol && superTypeSymbols.indexOf(symbol) === -1) { - superTypeSymbols.push(symbol); - } - } -} - -function getDescendantTypeSymbols(typeSymbol: Symbol) { - let descendantTypeSymbols = descendantTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)]; - if (descendantTypeSymbols) { - return descendantTypeSymbols; - } - - descendantTypeSymbols = []; - for (let symbolId in ancestorTypeSymbolsForTypeSymbol) { - let ancestorTypeSymbols = ancestorTypeSymbolsForTypeSymbol[symbolId]; - if (!Array.isArray(ancestorTypeSymbols) || ancestorTypeSymbols.indexOf(typeSymbol) === -1) { - continue; - } - - let ancestorTypeSymbol = typeSymbolsById[symbolId]; - if (descendantTypeSymbols.indexOf(ancestorTypeSymbol) === -1) { - descendantTypeSymbols.push(ancestorTypeSymbol); - } - } - - return descendantTypeSymbolsForTypeSymbol[getSymbolId(typeSymbol)] = descendantTypeSymbols; -} - -/** - * Get the SyntaxKind Symbols associated with a node type Symbol. - */ -function getSyntaxKindSymbolsForTypeSymbol(typeSymbol: Symbol, ensureExists?: boolean): Symbol[] { - let syntaxKindsForType = typeToSyntaxKinds[getSymbolId(typeSymbol)]; - if (!syntaxKindsForType && ensureExists) { - syntaxKindsForType = []; - typeToSyntaxKinds[getSymbolId(typeSymbol)] = syntaxKindsForType; - } - - return syntaxKindsForType; -} - -function getDescendantSyntaxKindSymbolsForTypeName(typeName: string): Symbol[] { - let symbols: Symbol[] = []; - let typeNames = splitTypeName(typeName); - for (let typeName of typeNames) { - let typeSymbol = resolveExportedQualifiedName(tsModuleSymbol, typeName, SymbolFlags.Type); - if (typeSymbol) { - let kindSymbols = getDescendantSyntaxKindSymbolsForTypeSymbol(typeSymbol); - for (let kindSymbol of kindSymbols) { - if (symbols.indexOf(kindSymbol) === -1) { - symbols.push(kindSymbol); - } - } - } - } - - return symbols; -} - -function getDescendantSyntaxKindSymbolsForTypeSymbol(typeSymbol: Symbol): Symbol[] { - let descendantSyntaxKindSymbols = descendantSyntaxKindSymbolsForTypeSymbol[getSymbolId(typeSymbol)]; - if (descendantSyntaxKindSymbols) { - return descendantSyntaxKindSymbols; - } - - descendantSyntaxKindSymbols = []; - for (let descendantOrSelfTypeSymbol of [typeSymbol, ...getDescendantTypeSymbols(typeSymbol)]) { - let kindSymbols = getSyntaxKindSymbolsForTypeSymbol(descendantOrSelfTypeSymbol) || emptyArray; - for (let kindSymbol of kindSymbols) { - if (descendantSyntaxKindSymbols.indexOf(kindSymbol) === -1) { - descendantSyntaxKindSymbols.push(kindSymbol); - } - } - } - - if (!findFirstAnnotation(typeSymbol, KindAnnotation.match)) { - let decl = typeSymbol.declarations[0]; - if (isTypeAliasDeclaration(decl)) { - let superTypes = getSuperTypeSymbols(typeSymbol); - for (let typeSymbol of superTypes) { - let kindSymbols = getDescendantSyntaxKindSymbolsForTypeSymbol(typeSymbol); - for (let kindSymbol of kindSymbols) { - if (descendantSyntaxKindSymbols.indexOf(kindSymbol) === -1) { - descendantSyntaxKindSymbols.push(kindSymbol); - } - } - } - } - } - - return descendantSyntaxKindSymbolsForTypeSymbol[getSymbolId(typeSymbol)] = descendantSyntaxKindSymbols; -} - -function getCompilerOptions() { - let options = getDefaultCompilerOptions(); - options.noResolve = true; - options.noLib = true; - return options; -} - -function createLineWrappingTextWriter(newLine: string, maxWidth: number): EmitTextWriter { - let writer = createTextWriter(newLine); - let noWrap = false; - let baseWrite = writer.write; - writer.write = writeWrap; - return writer; - - function writeWrap(text: string) { - let textTrimRight = text.replace(/\s+$/, ''); - if (writer.getColumn() + textTrimRight.length > maxWidth) { - writer.writeLine(); - writer.increaseIndent(); - baseWrite(text.replace(/^\s+/, '')); - writer.decreaseIndent(); - } - else { - baseWrite(text); - } - } -} - -// -// Annotations -// - -function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation; -function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation; -function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation { - for (let annotation of getAnnotations(symbol)) { - if (match(annotation)) { - return annotation; - } - } - - return undefined; -} - -function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation[]; -function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[]; -function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[] { - let annotations: TAnnotation[]; - for (let annotation of getAnnotations(symbol)) { - if (match(annotation)) { - if (!annotations) { - annotations = []; - } - - annotations.push(annotation); - } - } - return annotations || emptyArray; -} - -function getAnnotations(symbol: Symbol): Annotation[] { - let annotations = symbolToAnnotations[getSymbolId(symbol)]; - if (annotations) { - return annotations; - } - - annotations = []; - - for (let decl of symbol.declarations) { - let leadingCommentRanges = getLeadingCommentRanges(typesSourceFile.text, decl.pos); - if (leadingCommentRanges) { - for (let range of leadingCommentRanges) { - parseAnnotations(decl, range, annotations); - } - } - } - - return symbolToAnnotations[getSymbolId(symbol)] = annotations; -} - -function getLiteralValue(location: Node, expr: Expression): any { - switch (expr.kind) { - case SyntaxKind.TrueKeyword: - return true; - - case SyntaxKind.FalseKeyword: - return false; - - case SyntaxKind.NullKeyword: - return null; - - case SyntaxKind.VoidExpression: - return undefined; - - case SyntaxKind.StringLiteral: - return (expr).text; - - case SyntaxKind.NoSubstitutionTemplateLiteral: - return (expr).text; - - case SyntaxKind.NumericLiteral: - return Number((expr).text); - - case SyntaxKind.PropertyAccessExpression: - return getEnumLiteralValue(location, expr.getText()); - - case SyntaxKind.ArrayLiteralExpression: - return getArrayLiteralValue(location, expr); - - case SyntaxKind.ObjectLiteralExpression: - return getObjectLiteralValue(location, expr); - } -} - -function getArrayLiteralValue(location: Node, expr: ArrayLiteralExpression) { - let values: any[] = []; - for (let element of expr.elements) { - let value = getLiteralValue(location, element); - values.push(value); - } - return values; -} - -function getObjectLiteralValue(location: Node, expr: ObjectLiteralExpression) { - let obj: Map = {}; - for (let element of expr.properties) { - if (isPropertyAssignment(element)) { - let name = element.name; - if (isIdentifier(name)) { - obj[name.text] = getLiteralValue(location, element.initializer); - } - } - } - return obj; -} - -function parseAnnotations(location: Node, range: CommentRange, annotations: Annotation[]) { - let text = typesSourceFile.text; - let comment = text.substring(range.pos, range.end); - let annotationMatch: RegExpExecArray; - while (annotationMatch = annotationPattern.exec(comment)) { - let annotation = parseAnnotation(location, annotationMatch[1]); - if (annotation) { - annotations.push(annotation); - } - } -} - -function parseAnnotation(location: Node, annotationSource: string) { - let evalSourceFile = createSourceFile("eval.ts", annotationSource, options.target, true); - let statements = evalSourceFile.statements; - if (statements.length === 0) { - return undefined; - } - - let stmt = statements[0]; - if (stmt.kind !== SyntaxKind.ExpressionStatement) { - return undefined; - } - - let expr = (stmt).expression; - if (expr.kind === SyntaxKind.Identifier) { - return createAnnotation((expr).text, emptyArray); - } - else if (expr.kind === SyntaxKind.CallExpression) { - let call = expr; - if (call.expression.kind !== SyntaxKind.Identifier) { - return undefined; - } - - let _arguments: any[] = []; - for (let argument of call.arguments) { - _arguments.push(getLiteralValue(location, argument)); - } - - return createAnnotation((call.expression).text, _arguments); - } - else { - return undefined; - } -} - -function annotation(name: string) { - return function(target: T) { - annotationConstructors[name] = target; - return target; - } -} - -class Annotation { - public name: string; - public arguments: any[]; - constructor(_arguments: any[]) { - this.arguments = _arguments; - } - - public static match(annotation: Annotation): boolean { - return annotation instanceof this; - } -} - -@annotation("kind") -class KindAnnotation extends Annotation { - public name = "kind"; - public kind: SyntaxKind; - public kindSymbol: Symbol; - public options: KindOptions; - constructor([{ value, symbol }, { create = true, update = true, test = true } = {}, ..._arguments]: [EnumValue, KindOptions, any]) { - super(_arguments); - this.kind = value; - this.kindSymbol = symbol; - this.options = { create, update, test }; - } - - public static match(annotation: Annotation): annotation is KindAnnotation { - return annotation instanceof KindAnnotation; - } -} - -@annotation("factoryhidden") -class FactoryHiddenAnnotation extends Annotation { - public name = "factoryhidden"; - public propertyName: string; - public hidden: boolean; - constructor([ propertyName, hidden, ..._arguments]: [string | boolean, boolean, any]) { - super(_arguments); - if (typeof propertyName === "boolean") { - this.hidden = propertyName; - } - else if (typeof propertyName === "string") { - this.propertyName = propertyName; - if (typeof hidden === "boolean") { - this.hidden = hidden; - } - else { - this.hidden = true; - } - } - else { - this.hidden = true; - } - } - - public static match(annotation: Annotation): annotation is FactoryHiddenAnnotation { - return annotation instanceof FactoryHiddenAnnotation; - } -} - -@annotation("factoryorder") -class FactoryOrderAnnotation extends Annotation { - public name = "factoryorder"; - public propertyNames: string[]; - constructor(propertyNames: string[]) { - super([]); - this.propertyNames = propertyNames; - } - - public static match(annotation: Annotation): annotation is FactoryOrderAnnotation { - return annotation instanceof FactoryOrderAnnotation; - } -} - -@annotation("factoryparam") -class FactoryParamAnnotation extends Annotation { - public name = "factoryparam"; - public propertyName: string; - constructor([propertyName, ..._arguments]: [string, any]) { - super(_arguments); - this.propertyName = propertyName; - } - - public static match(annotation: Annotation): annotation is FactoryParamAnnotation { - return annotation instanceof FactoryParamAnnotation; - } -} - -@annotation("visitor") -class MemberVisitorAnnotation extends Annotation { - public name = "visitor"; - public functionName: string; - constructor([functionName, ..._arguments]: [string, any]) { - super(_arguments); - this.functionName = functionName; - } - - public static match(annotation: Annotation): annotation is MemberVisitorAnnotation { - return annotation instanceof MemberVisitorAnnotation; - } -} - -@annotation("newlexicalenvironment") -class NewLexicalEnvironmentAnnotation extends Annotation { - public name = "newlexicalenvironment"; - - public static match(annotation: Annotation): annotation is NewLexicalEnvironmentAnnotation { - return annotation instanceof NewLexicalEnvironmentAnnotation; - } -} - -@annotation("nodetest") -class NodeTestAnnotation extends Annotation { - public name = "nodetest"; - public functionName: string; - constructor([functionName, ..._arguments]: [string, any]) { - super(_arguments); - this.functionName = functionName - } - - public static match(annotation: Annotation): annotation is NodeTestAnnotation { - return annotation instanceof NodeTestAnnotation; - } -} - -function createAnnotation(name: string, _arguments: any[]): Annotation { - let ctor = getProperty(annotationConstructors, name); - if (ctor) { - return new ctor(_arguments); - } - else { - let annotation = new Annotation(_arguments); - annotation.name = name; - return annotation; - } -} - -function getFactoryHiddenStateForSymbol(symbol: Symbol): FactoryHiddenState { - let annotation: FactoryHiddenAnnotation; - if (annotation = findFirstAnnotation(symbol, annotation => FactoryHiddenAnnotation.match(annotation) && annotation.propertyName === undefined)) { - return annotation.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible; - } - - return FactoryHiddenState.None; -} - -function getFactoryHiddenStateForProperty(container: Symbol, propertyName: string): FactoryHiddenState { - let hiddenStates: FactoryHiddenStateResult[] = []; - let hiddenStateForSource: FactoryHiddenStateResult[] = []; - - // find all the hidden states for this property - getFactoryHiddenStateForPropertyWorker(container, /*depth*/ 0); - if (hiddenStates.length === 0) { - return FactoryHiddenState.None; - } - else if (hiddenStates.length === 1) { - return hiddenStates[0].state; - } - - let closestMatch: FactoryHiddenStateResult; - for (let hiddenState of hiddenStates) { - if (closestMatch === undefined || hiddenState.depth < closestMatch.depth) { - closestMatch = hiddenState; - } - } - - return closestMatch.state; - - interface FactoryHiddenStateResult { - state: FactoryHiddenState; - source?: Symbol; - depth?: number; - } - - function getFactoryHiddenStateForPropertyWorker(source: Symbol, depth: number): void { - let state: FactoryHiddenState; - - let result = hiddenStateForSource[getSymbolId(source)]; - if (result) { - if (depth > result.depth) { - result.depth = depth; - } - - return; - } - - // First, check for a property-specific `@factoryhidden` annotation on the container (e.g. `@factoryhidden("x", true)`) - let annotation = findFirstAnnotation(source, annotation => FactoryHiddenAnnotation.match(annotation) && annotation.propertyName === propertyName); - if (annotation) { - // encode the depth for later comparison - state = annotation.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible; - } - - let property: Symbol; - if (!state) { - property = source.members ? getProperty(source.members, propertyName) : undefined; - if (property) { - state = getFactoryHiddenStateForSymbol(property); - } - } - - if (!state) { - state = getFactoryHiddenStateForSymbol(source); - } - - if (!state && property) { - state = FactoryHiddenState.Visible; - } - - if (state) { - let result = { state, source, depth }; - hiddenStates.push(result); - hiddenStateForSource[getSymbolId(source)] = result; - if (depth === 0) { - return; - } - } - - for (let superType of getSuperTypeSymbols(source)) { - getFactoryHiddenStateForPropertyWorker(superType, depth + 1); - } - } -} - - -function isFactoryParamProperty(container: Symbol, propertyName: string): boolean { - if (findFirstAnnotation(container, annotation => FactoryParamAnnotation.match(annotation) && annotation.propertyName === propertyName)) { - return true; - } - - let property = container.members ? getProperty(container.members, propertyName) : undefined; - if (property) { - if (findFirstAnnotation(property, annotation => FactoryParamAnnotation.match(annotation) && annotation.propertyName === undefined)) { - return true; - } - } - else { - for (let superType of getSuperTypeSymbols(container)) { - if (isFactoryParamProperty(superType, propertyName)) { - return true; - } - } - } - - return false; -} - -function getFactoryOrder(symbol: Symbol, inherited?: boolean): string[] { - let annotation = findFirstAnnotation(symbol, FactoryOrderAnnotation.match); - if (annotation) { - return annotation.propertyNames; - } - - let propertyNames: string[]; - if (inherited) { - for (let superType of getSuperTypeSymbols(symbol)) { - let superTypeOrder = getFactoryOrder(superType, /*inherited*/ true); - if (superTypeOrder && superTypeOrder.length > 0) { - if (!propertyNames) { - propertyNames = []; - } - - for (let propertyName of superTypeOrder) { - if (propertyNames.indexOf(propertyName) === -1) { - propertyNames.push(propertyName); - } - } - } - } - } - - return propertyNames; -} - -function startsNewLexicalEnvironment(symbol: Symbol): boolean { - return !!findFirstAnnotation(symbol, NewLexicalEnvironmentAnnotation.match); -} - -function getCreateFunctionName(syntaxNode: SyntaxNode) { - let create = syntaxNode.options.create; - return typeof create === "string" ? create : `create${syntaxNode.kindName}`; -} - -function getUpdateFunctionName(syntaxNode: SyntaxNode) { - let update = syntaxNode.options.update; - return typeof update === "string" ? update : `update${syntaxNode.kindName}`; -} - -// Main entry point -main(); \ No newline at end of file diff --git a/scripts/processTypes/discovery.ts b/scripts/processTypes/discovery.ts new file mode 100644 index 00000000000..ca68e7f1426 --- /dev/null +++ b/scripts/processTypes/discovery.ts @@ -0,0 +1,555 @@ +import { SyntaxKind, Symbol, SymbolFlags, Map, } from "./typescript-internal"; +import { hasProperty, getProperty } from "./utilities"; +import { getType, getTypes, makeArrayType, resolveQualifiedName, annotation, EnumValue, Annotation, TypeInfo, PropertyInfo } from "./types"; + +export interface DiscoveryResult { + createableNodes: SyntaxNode[]; + updateableNodes: SyntaxNode[]; + testableNodes: SyntaxNode[]; + testableTypes: SyntaxType[]; +} + +export interface SyntaxType { + type: TypeInfo; + typeName: string; + superTypes: SyntaxType[]; + directSyntaxNodes: SyntaxNode[]; + syntaxNodes?: SyntaxNode[]; + testFunctionName?: string; +} + +export interface SyntaxNode { + kind: SyntaxKind; + kindName: string; + typeName: string; + createFunctionName: string; + createParameters: SyntaxMember[]; + updateFunctionName: string; + updateParameters: SyntaxMember[]; + testFunctionName: string; +} + +export interface SyntaxMember { + propertyName?: string; + parameterName?: string; + parameterTypeName: string; + isFactoryParameter?: boolean; + isNodeArray?: boolean; + isModifiersArray?: boolean; + testFunctionName?: string; + visitorFunctionName?: string; +} + +/** + * Discovers type information and symbols for various SyntaxNodes + */ +export function discover(): DiscoveryResult { + const typesReferencedByProperties: boolean[] = []; + const syntaxTypeForTypeInfo: SyntaxType[] = []; + const createableNodes: SyntaxNode[] = []; + const updateableNodes: SyntaxNode[] = []; + const testableNodes: SyntaxNode[] = []; + const syntaxTypes: SyntaxType[] = []; + const testableTypes: SyntaxType[] = []; + const localNames: Map = {}; + + let types = getTypes("ts"); + let nodeType = getType("ts.Node"); + let modifierType = getType("ts.Modifier"); + let statementType = getType("ts.Statement"); + let conciseBodyType = getType("ts.ConciseBody"); + let functionBodyType = getType("ts.FunctionBody"); + let moduleBodyType = getType("ts.ModuleBody"); + let sourceFileType = getType("ts.SourceFile"); + let nodeArrayType = getType("ts.NodeArray"); + let modifiersArrayType = getType("ts.ModifiersArray"); + + for (let type of types) { + discoverType(type); + } + + for (let type of syntaxTypes) { + discoverTestableType(type); + } + + createableNodes.sort((a, b) => a.kind - b.kind); + updateableNodes.sort((a, b) => a.kind - b.kind); + testableNodes.sort((a, b) => a.kind - b.kind); + testableTypes.sort((a, b) => a.toString().localeCompare(b.toString())); + + return { createableNodes, updateableNodes, testableNodes, testableTypes }; + + function discoverType(type: TypeInfo) { + let syntaxType = syntaxTypeForTypeInfo[type.id]; + if (!syntaxType) { + if (nodeType.isAssignableFrom(type)) { + let superTypes: SyntaxType[] = []; + let directSyntaxNodes: SyntaxNode[] = []; + let typeName = type.toString(); + + syntaxType = { + type, + typeName, + superTypes, + directSyntaxNodes + }; + + syntaxTypes.push(syntaxType); + syntaxTypeForTypeInfo[type.id] = syntaxType; + + for (let superType of type.getSuperTypes()) { + let superSyntaxType = discoverType(superType); + if (superSyntaxType) { + superTypes.push(superSyntaxType); + } + } + + for (let kind of type.findAllAnnotations(/*inherited*/ false, KindAnnotation.match)) { + directSyntaxNodes.push(discoverKind(type, kind)); + } + } + } + return syntaxType; + } + + function discoverKind(type: TypeInfo, kind: KindAnnotation) { + let kindName = kind.kindSymbol.name; + let typeName = type.toString(); + let createFunctionName = discoverFunctionName(kindName, "create", kind.create); + let createParameters: SyntaxMember[] = createFunctionName ? [] : undefined; + let updateFunctionName = discoverFunctionName(kindName, "update", kind.update); + let updateParameters: SyntaxMember[] = updateFunctionName ? [] : undefined; + let testFunctionName = discoverFunctionName(kindName, "is", kind.test); + if (type.name === "StringLiteral") { + debugger; + } + for (let property of type.getProperties(/*inherited*/ true)) { + if (FactoryHiddenAnnotation.getState(type, property.name) === FactoryHiddenState.Hidden) { + continue; + } + + let isFactoryParameter = property.findFirstAnnotation(/*inherited*/ true, FactoryParamAnnotation.match) !== undefined; + let isNode = nodeType.isAssignableFrom(property.propertyType); + let isModifiersArray = modifiersArrayType.isAssignableFrom(property.propertyType); + let isNodeArray = !isModifiersArray && nodeArrayType.isAssignableFrom(property.propertyType); + if (isFactoryParameter || isNode || isNodeArray || isModifiersArray) { + let propertyName = property.name; + let parameterName = property.name === "arguments" ? "_arguments" : property.name; + let parameterType: TypeInfo; + let nodeType: TypeInfo; + if (isModifiersArray) { + nodeType = modifierType; + parameterType = makeArrayType(nodeType); + } + else if (isNodeArray) { + nodeType = property.propertyType.getGenericTypeArguments()[0]; + parameterType = makeArrayType(nodeType); + } + else if (isNode) { + nodeType = property.propertyType; + parameterType = nodeType; + } + else { + parameterType = property.propertyType; + } + + if (nodeType) { + typesReferencedByProperties[nodeType.id] = true; + discoverType(nodeType); + } + + let parameterTypeName = parameterType.toString(); + let testFunctionName: string; + let visitorFunctionName: string; + if (!isFactoryParameter) { + switch (property.propertyType) { + case nodeType: break; + case statementType: visitorFunctionName = "transformer.visitStatement"; break; + case conciseBodyType: visitorFunctionName = "transformer.visitConciseBody"; break; + case functionBodyType: visitorFunctionName = "transformer.visitFunctionBody"; break; + case moduleBodyType: visitorFunctionName = "transformer.visitModuleBody"; break; + case sourceFileType: visitorFunctionName = "transformer.visitSourceFile"; break; + default: + if (isModifiersArray || isNodeArray) { + visitorFunctionName = "transformer.visitNodes"; + visitorFunctionName = "transformer.visitNodes"; + } + else if (isNode) { + visitorFunctionName = "transformer.visitNode"; + } + + if (isModifiersArray) { + testFunctionName = "isModifier"; + } + else if (isNodeArray || isNode) { + testFunctionName = getIsAnyNodeFunctionName(nodeType); + } + break; + } + } + + let syntaxMember = { + propertyName, + parameterName, + parameterTypeName, + isFactoryParameter, + isNodeArray, + isModifiersArray, + testFunctionName, + visitorFunctionName + }; + + if (createFunctionName) { + createParameters.push(syntaxMember); + } + + if (updateFunctionName && !isFactoryParameter) { + updateParameters.push(syntaxMember); + } + } + } + + let factoryOrder = type.findFirstAnnotation(/*inherited*/ true, FactoryOrderAnnotation.match); + if (factoryOrder) { + if (createFunctionName) { + createParameters = sortMembers(createParameters, factoryOrder.propertyNames); + } + + if (updateFunctionName) { + updateParameters = sortMembers(updateParameters, factoryOrder.propertyNames); + } + } + + let syntaxNode = { + kind: kind.kind, + kindName, + typeName, + createFunctionName, + createParameters, + updateFunctionName, + updateParameters, + testFunctionName + }; + + if (createFunctionName) { + createableNodes.push(syntaxNode); + localNames[createFunctionName] = createFunctionName; + } + + if (updateFunctionName && updateParameters.length > 0) { + updateableNodes.push(syntaxNode); + localNames[updateFunctionName] = updateFunctionName; + } + + if (testFunctionName) { + testableNodes.push(syntaxNode); + localNames[testFunctionName] = testFunctionName; + } + + return syntaxNode; + } + + function sortMembers(members: SyntaxMember[], order: string[]) { + let indices = members.map((_, i) => i); + indices.sort((a, b) => { + let aOverride = order.indexOf(members[a].propertyName); + let bOverride = order.indexOf(members[b].propertyName); + if (aOverride >= 0) { + if (bOverride >= 0) { + return aOverride - bOverride; + } + + return -1; + } + else if (bOverride >= 0) { + return +1; + } + + return a - b; + }); + + return indices.map(i => members[i]); + } + + function discoverFunctionName(kindName: string, prefix: string, option: boolean | string) { + if (typeof option === "string") { + return option; + } + else if (option) { + let functionName = prefix + kindName; + if (!hasProperty(localNames, functionName)) { + let symbol = resolveQualifiedName("ts." + functionName, SymbolFlags.Function); + if (!symbol) { + return functionName; + } + } + } + + return undefined; + } + + function getIsAnyNodeFunctionName(type: TypeInfo) { + if (type !== nodeType) { + let functionName: string; + let nodeTest = type.findFirstAnnotation(/*inherited*/ false, NodeTestAnnotation.match); + if (nodeTest) { + return nodeTest.functionName; + } + else if (type.isTypeAlias || type.isInterface) { + return "is" + getKindOrTypeNameForType(type); + } + else if (type.isUnionType) { + return "is" + type.getConstituentTypes().map(getKindOrTypeNameForType).join("Or"); + } + } + return undefined; + } + + function discoverTestableType(syntaxType: SyntaxType) { + if (syntaxType.type !== nodeType && !syntaxType.syntaxNodes) { + syntaxType.syntaxNodes = []; + if (syntaxType.type.findFirstAnnotation(/*inherited*/ false, KindAnnotation.match)) { + copySyntaxNodes(syntaxType.type, syntaxType.syntaxNodes, []); + } + else { + discoverSyntaxNodes(syntaxType.type, syntaxType.syntaxNodes, []); + } + + if (syntaxType.syntaxNodes.length > 0) { + let testFunctionName = discoverIsAnyNodeFunctionName(syntaxType.type); + if (testFunctionName) { + syntaxType.testFunctionName = testFunctionName; + testableTypes.push(syntaxType); + } + } + } + } + + function discoverSyntaxNodes(type: TypeInfo, syntaxNodes: SyntaxNode[], seen: boolean[]) { + copySyntaxNodes(type, syntaxNodes, seen); + + for (let aliasType of type.getAliases()) { + copySyntaxNodes(aliasType, syntaxNodes, seen); + } + + if (type.isInterface) { + for (let subType of type.getSubTypes()) { + discoverSyntaxNodes(subType, syntaxNodes, seen); + } + } + + if (type.isTypeAlias) { + discoverSyntaxNodes(type.getAliasedType(), syntaxNodes, seen); + } + + if (type.isUnionType) { + for (let constituentType of type.getConstituentTypes()) { + discoverSyntaxNodes(constituentType, syntaxNodes, seen); + } + } + } + + function copySyntaxNodes(type: TypeInfo, syntaxNodes: SyntaxNode[], seen: boolean[]) { + let syntaxType = syntaxTypeForTypeInfo[type.id]; + if (syntaxType) { + for (let syntaxNode of syntaxType.directSyntaxNodes) { + if (!seen[syntaxNode.kind]) { + seen[syntaxNode.kind] = true; + syntaxNodes.push(syntaxNode); + } + } + } + } + + function discoverIsAnyNodeFunctionName(type: TypeInfo) { + if (typesReferencedByProperties[type.id]) { + let functionName = getIsAnyNodeFunctionName(type); + if (functionName && !hasProperty(localNames, functionName)) { + let symbol = resolveQualifiedName("ts." + functionName, SymbolFlags.Function); + if (!symbol) { + localNames[functionName] = functionName; + return functionName; + } + } + } + return undefined; + } + + function getKindOrTypeNameForType(type: TypeInfo) { + let kinds = type.findAllAnnotations(/*inherited*/ false, KindAnnotation.match); + if (kinds.length === 1) { + return kinds[0].kindSymbol.name; + } + + return type.name; + } +} + +export interface KindOptions { + create: boolean | string; + update: boolean | string; + test: boolean | string; +} + +@annotation("kind", { inherited: false }) +export class KindAnnotation extends Annotation { + public kind: SyntaxKind; + public kindSymbol: Symbol; + public create: boolean | string; + public update: boolean | string; + public test: boolean | string; + + constructor([{ value, symbol }, { create = true, update = true, test = true } = {}, ..._arguments]: [EnumValue, KindOptions, any]) { + super(_arguments); + this.kind = value; + this.kindSymbol = symbol; + this.create = create; + this.update = update; + this.test = test; + } + + public static match(annotation: Annotation): annotation is KindAnnotation { + return annotation instanceof KindAnnotation; + } +} + +export const enum FactoryHiddenState { + None, + Hidden, + Visible +} + +@annotation("factoryhidden", { inherited: true, allowMultiple: true }) +export class FactoryHiddenAnnotation extends Annotation { + public propertyName: string; + public hidden: boolean; + constructor([ propertyName, hidden, ..._arguments]: [string | boolean, boolean, any]) { + super(_arguments); + if (typeof propertyName === "boolean") { + this.hidden = propertyName; + } + else if (typeof propertyName === "string") { + this.propertyName = propertyName; + if (typeof hidden === "boolean") { + this.hidden = hidden; + } + else { + this.hidden = true; + } + } + else { + this.hidden = true; + } + } + + public static getState(type: TypeInfo, propertyName?: string) { + if (propertyName) { + return this.getStateForProperty(type, propertyName); + } + else { + return this.getStateForType(type); + } + } + + private static getStateForProperty(type: TypeInfo, propertyName: string) { + let factoryHiddenState = FactoryHiddenState.None; + let inheritedTypes: TypeInfo[] = [type]; + while (factoryHiddenState === FactoryHiddenState.None && inheritedTypes.length) { + [factoryHiddenState, inheritedTypes] = this.getStateForPropertyBreadthFirst(inheritedTypes, propertyName); + } + return factoryHiddenState; + } + + private static getStateForPropertyBreadthFirst(types: TypeInfo[], propertyName: string): [FactoryHiddenState, TypeInfo[]] { + let inheritedTypes: TypeInfo[] = []; + let factoryHidden: FactoryHiddenAnnotation; + let factoryHiddenState: FactoryHiddenState = FactoryHiddenState.None; + for (let type of types) { + let property = type.getProperty(propertyName, /*inherited*/ false); + if (property) { + if (factoryHidden = property.findFirstAnnotation(/*inherited*/ false, FactoryHiddenAnnotation.match)) { + factoryHiddenState = factoryHidden.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible; + break; + } + } + + if (factoryHidden = type.findFirstAnnotation(/*inherited*/ false, FactoryHiddenAnnotation.matchProperty(propertyName))) { + factoryHiddenState = factoryHidden.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible; + break; + } + + if (property) { + factoryHiddenState = FactoryHiddenState.Visible; + break; + } + + if (type.isInterface) { + inheritedTypes = inheritedTypes.concat(type.getSuperTypes()); + } + else if (type.isTypeAlias) { + inheritedTypes.push(type.getAliasedType()); + } + else if (type.isUnionType) { + inheritedTypes = inheritedTypes.concat(type.getConstituentTypes()); + } + } + + return [factoryHiddenState, inheritedTypes]; + } + + private static getStateForType(type: TypeInfo) { + let annotation = type.findFirstAnnotation(/*inherited*/ false, this.matchProperty(undefined)); + return annotation ? annotation.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible : FactoryHiddenState.None; + } + + public static matchProperty(propertyName: string): (annotation: Annotation) => annotation is FactoryHiddenAnnotation { + return (annotation): annotation is FactoryHiddenAnnotation => this.match(annotation) && annotation.propertyName === propertyName; + } + + public static match(annotation: Annotation): annotation is FactoryHiddenAnnotation { + return annotation instanceof FactoryHiddenAnnotation; + } +} + +@annotation("factoryorder", { inherited: true }) +export class FactoryOrderAnnotation extends Annotation { + public propertyNames: string[]; + constructor(propertyNames: string[]) { + super([]); + this.propertyNames = propertyNames; + } + + public static match(annotation: Annotation): annotation is FactoryOrderAnnotation { + return annotation instanceof FactoryOrderAnnotation; + } +} + +@annotation("factoryparam", { inherited: true, allowMultiple: true }) +export class FactoryParamAnnotation extends Annotation { + public propertyName: string; + constructor([propertyName, ..._arguments]: [string, any]) { + super(_arguments); + this.propertyName = propertyName; + } + + public static matchProperty(propertyName: string): (annotation: Annotation) => annotation is FactoryParamAnnotation { + return (annotation): annotation is FactoryParamAnnotation => this.match(annotation) && annotation.propertyName === propertyName; + } + + public static match(annotation: Annotation): annotation is FactoryParamAnnotation { + return annotation instanceof FactoryParamAnnotation; + } +} + +@annotation("nodetest", { inherited: false, allowMultiple: false }) +export class NodeTestAnnotation extends Annotation { + public functionName: string; + constructor([functionName, ..._arguments]: [string, any]) { + super(_arguments); + this.functionName = functionName + } + + public static match(annotation: Annotation): annotation is NodeTestAnnotation { + return annotation instanceof NodeTestAnnotation; + } +} \ No newline at end of file diff --git a/scripts/processTypes/processTypes.ts b/scripts/processTypes/processTypes.ts new file mode 100644 index 00000000000..703e9c4d50b --- /dev/null +++ b/scripts/processTypes/processTypes.ts @@ -0,0 +1,105 @@ +import { sys, getDefaultCompilerOptions, createProgram, createCompilerHost } from "./typescript-internal"; +import { loadSourceFiles } from "./types"; +import { discover, DiscoveryResult } from "./discovery"; +import { combinePaths } from "./utilities"; + +main(); + +function main() { + if (sys.args.length < 3) { + sys.write("Usage:" + sys.newLine) + sys.write("\tnode processTypes.js " + sys.newLine); + return; + } + + const typesTsFileName = sys.resolvePath(sys.args[0]); + const factoryTsFileName = sys.resolvePath(sys.args[1]); + const utilitiesTsFileName = sys.resolvePath(sys.args[2]); + + loadSourceFiles([ + /*typesTsFileName*/ sys.resolvePath(sys.args[0]), + /*factoryTsFileName*/ sys.resolvePath(sys.args[1]), + /*utilitiesTsFileName*/ sys.resolvePath(sys.args[2]) + ]); + + // Discover syntax nodes + const discovery = discover(); + + // Emit the generated factory output file + const factoryDirectory = sys.resolvePath(combinePaths(factoryTsFileName, "..")); + const factoryOutputFile = combinePaths(factoryDirectory, "factory.generated.ts"); + const factoryOutput = generateFactory(discovery); + sys.writeFile(factoryOutputFile, factoryOutput); +} + +export function generateFactory(discovery: DiscoveryResult) { + return ` +// +/// +namespace ts {${each(discovery.createableNodes, syntaxNode => ` + export function ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => `${member.parameterName}?: ${member.parameterTypeName}, `)}location?: TextRange, flags?: NodeFlags): ${syntaxNode.typeName} { + let node = createNode<${syntaxNode.typeName}>(SyntaxKind.${syntaxNode.kindName}, location, flags); ${each(syntaxNode.createParameters, member => ` + if (${member.parameterName}) ${ + member.isModifiersArray + ? `setModifiers(node, ${member.parameterName});` + : member.isNodeArray + ? `node.${member.propertyName} = createNodeArray(${member.parameterName});` + : `node.${member.propertyName} = ${member.parameterName};` + }`)} + return node; + }`)}${each(discovery.updateableNodes, syntaxNode => ` + export function ${syntaxNode.updateFunctionName}(node: ${syntaxNode.typeName}${each(syntaxNode.updateParameters, member => `, ${member.parameterName}: ${member.parameterTypeName}`)}): ${syntaxNode.typeName} { + if (${each(syntaxNode.updateParameters, member => `${member.parameterName} !== node.${member.propertyName}`, ` || `)}) { + let newNode = ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => + member.isFactoryParameter + ? `node.${member.propertyName}` + : member.parameterName, `, `)}); + return updateFrom(node, newNode); + } + return node; + }`)}${each(discovery.testableNodes, syntaxNode => ` + export function ${syntaxNode.testFunctionName}(node: Node): node is ${syntaxNode.typeName} { + return node && node.kind === SyntaxKind.${syntaxNode.kindName}; + }`)}${each(discovery.testableTypes, syntaxType => ` + export function ${syntaxType.testFunctionName}(node: Node): node is ${syntaxType.typeName} { + if (node) { + switch (node.kind) {${each(syntaxType.syntaxNodes, syntaxNode => ` + case SyntaxKind.${syntaxNode.kindName}:`)} + return true; + } + } + return false; + }`)} + export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode; + export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node { + if (node) { + switch (node.kind) {${each(discovery.createableNodes, syntaxNode => ` + case SyntaxKind.${syntaxNode.kindName}: + return ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => + `(<${syntaxNode.typeName}>node).${member.propertyName}, ` + )}location, flags);`)} + } + } + return node; + } + export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node { + if (node) { + switch (node.kind) {${each(discovery.updateableNodes, syntaxNode => ` + case SyntaxKind.${syntaxNode.kindName}: + return ${syntaxNode.updateFunctionName}(<${syntaxNode.typeName}>node${each(syntaxNode.updateParameters, member => + member.visitorFunctionName && member.testFunctionName + ? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor, ${member.testFunctionName})` + : member.visitorFunctionName + ? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor)` + : `, (<${syntaxNode.typeName}>node).${member.propertyName}` + )});`)} + } + } + return node; + } +}`; + + function each(items: T[], callbackfn: (item: T) => string, separator = ``) { + return items.map(callbackfn).join(separator); + } +} \ No newline at end of file diff --git a/scripts/processTypes/tsconfig.json b/scripts/processTypes/tsconfig.json new file mode 100644 index 00000000000..cd27adf97be --- /dev/null +++ b/scripts/processTypes/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "outDir": "../../built/scripts/processTypes/", + "experimentalDecorators": true, + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true + } +} \ No newline at end of file diff --git a/scripts/processTypes/types.ts b/scripts/processTypes/types.ts new file mode 100644 index 00000000000..5a7f1cb5b5c --- /dev/null +++ b/scripts/processTypes/types.ts @@ -0,0 +1,1222 @@ +import * as ts from "./typescript-internal" +import { Map, SyntaxKind, Node, Symbol, SymbolFlags, getSymbolId } from "./typescript-internal"; +import { hasProperty, getProperty } from "./utilities"; + +const typeInfoForSymbol: TypeInfo[] = []; +const typeInfoForName: Map = {}; +const typeInfoForUnion: Map = {}; +const typeInfoForTypeReference: Map = {}; +const subTypeRelationships: TypeInfo[][] = []; +const aliasRelationships: TypeInfo[][] = []; +const unionRelationships: TypeInfo[][] = []; +const propertyInfoForSymbol: PropertyInfo[] = []; +const annotationPattern = /@(\w+\s*[^\r\n]*)/g; +const symbolToAnnotations: Annotation[][] = []; +const annotationConstructors: Map<{ constructor: typeof Annotation; inherited: boolean; allowMultiple: boolean; }> = {}; +const options = getCompilerOptions(); +const host = ts.createCompilerHost(options); + +let globalArrayType: TypeInfo; +let checker: ts.TypeChecker; +let program: ts.Program; + +export interface EnumValue { + symbol: Symbol; + value: T; +} + +export abstract class TypeInfo implements Annotated { + private static nextId = 1; + private annotations: Annotation[]; + private allAnnotations: Annotation[]; + + public id = TypeInfo.nextId++; + public symbol: Symbol; + public name: string; + public members: PropertyInfo[] = []; + + constructor(symbol: Symbol, name: string) { + this.symbol = symbol; + this.name = name; + } + + public get isInterface() { return false; } + public get isTypeAlias() { return false; } + public get isOtherType() { return false; } + public get isUnionType() { return false; } + public get isGenericTypeParameter() { return false; } + public get hasGenericTypeParameters() { return false; } + public get isConstructedGenericType() { return false; } + + public getGenericTypeDefinition(): TypeInfo { + throw new TypeError(); + } + + public getGenericTypeParameters(): TypeInfo[] { + throw new TypeError(); + } + + public getGenericTypeArguments(): TypeInfo[] { + return []; + } + + public getSuperTypes(): TypeInfo[] { + return []; + } + + public getSubTypes(): TypeInfo[] { + return subTypeRelationships[this.id] || []; + } + + public getAliases(): TypeInfo[] { + return aliasRelationships[this.id] || []; + } + + public getRelatedUnionTypes(): TypeInfo[] { + return unionRelationships[this.id] || []; + } + + public getAliasedType(): TypeInfo { + return undefined; + } + + public getConstituentTypes(): TypeInfo[] { + return []; + } + + public makeGenericType(typeArguments: TypeInfo[]): TypeInfo { + throw new TypeError(); + } + + public isAssignableFrom(type: TypeInfo): boolean { + if (type === undefined) { + return false; + } + + if (this === type) { + return true; + } + + if (type.isUnionType) { + for (let constituentType of type.getConstituentTypes()) { + if (!this.isAssignableFrom(constituentType)) { + return false; + } + } + + return true; + } + + if (type.isTypeAlias) { + return this.isAssignableFrom(type.getAliasedType()); + } + + if (type.isConstructedGenericType) { + return this.isAssignableFrom(type.getGenericTypeDefinition()); + } + + if (this.isConstructedGenericType) { + return this.getGenericTypeDefinition().isAssignableFrom(type); + } + + if (this.isUnionType) { + if (type.isConstituentOf(this)) { + return true; + } + } + + if (this.isTypeAlias) { + if (this.getAliasedType().isAssignableFrom(type)) { + return true; + } + } + + if (this.isInterface) { + if (type.isSubTypeOf(this)) { + return true; + } + } + + if (this.isGenericTypeParameter) { + return true; + } + + return false; + } + + public isConstituentOf(type: TypeInfo): boolean { + if (type === undefined) { + return false; + } + + if (type === this) { + return true; + } + + if (type.isTypeAlias) { + return this.isConstituentOf(type.getAliasedType()); + } + + if (type.isUnionType) { + for (let constituentType of type.getConstituentTypes()) { + if (constituentType.isAssignableFrom(this)) { + return true; + } + } + } + + return false; + } + + public isSuperTypeOf(type: TypeInfo) { + if (type === undefined) { + return false; + } + + return type.isSubTypeOf(this); + } + + public isSubTypeOf(type: TypeInfo): boolean { + if (type === undefined) { + return false; + } + + if (type.isTypeAlias) { + return this.isSubTypeOf(type.getAliasedType()); + } + + if (this.isTypeAlias) { + return this.getAliasedType().isSubTypeOf(type); + } + + for (let superType of this.getSuperTypes()) { + if (superType === type) { + return true; + } + } + + for (let superType of this.getSuperTypes()) { + if (superType.isSubTypeOf(type)) { + return true; + } + } + + return false; + } + + public getProperty(propertyName: string, inherited: boolean) { + let properties = this.getProperties(inherited); + for (let property of properties) { + if (property.name === propertyName) { + return property; + } + } + + return undefined; + } + + public getProperties(inherited: boolean) { + let properties: PropertyInfo[]; + if (inherited) { + properties = this.members.slice(0); + } + else { + properties = []; + for (let member of this.members) { + if (member.containingType === this) { + properties.push(member); + } + } + } + + return properties; + } + + public getAnnotations(inherited: boolean) { + return inherited ? this.getInheritedAnnotations() : this.getOwnAnnotations(); + } + + public findAllAnnotations(inherited: boolean, match: (annotation: Annotation) => annotation is T): T[] { + return findAllAnnotationsOf(this, inherited, match); + } + + public findFirstAnnotation(inherited: boolean, match: (annotation: Annotation) => annotation is T): T { + return findFirstAnnotationOf(this, inherited, match); + } + + public toString(): string { + return this.name ? this.name : "any"; + } + + private getOwnAnnotations() { + if (!this.annotations) { + this.annotations = []; + if (this.symbol) { + for (let annotation of getAnnotations(this.symbol)) { + this.annotations.push(annotation); + } + } + } + + return this.annotations; + } + + private getInheritedAnnotations() { + if (!this.allAnnotations) { + this.allAnnotations = []; + let inheritedTypes = [this]; + let seen: Map = {}; + while (inheritedTypes.length > 0) { + inheritedTypes = this.fillBreadthFirstInheritedAnnotations(inheritedTypes, seen); + } + } + return this.allAnnotations; + } + + private fillBreadthFirstInheritedAnnotations(types: TypeInfo[], seen: Map) { + let inheritedTypes: TypeInfo[] = []; + for (let type of types) { + if (type.isInterface) { + inheritedTypes = inheritedTypes.concat(type.getSuperTypes()); + } + else if (type.isTypeAlias) { + inheritedTypes.push(type.getAliasedType()); + } + else if (type.isUnionType) { + inheritedTypes = inheritedTypes.concat(type.getConstituentTypes()); + } + + for (let annotation of type.getOwnAnnotations()) { + if (type === this || annotationMayBeInherited(annotation)) { + if (!annotationAllowsMultiple(annotation)) { + if (hasProperty(seen, annotation.name)) { + continue; + } + + seen[annotation.name] = true; + } + + this.allAnnotations.push(annotation); + } + } + } + + return inheritedTypes; + } +} + +abstract class GenericTypeInfo extends TypeInfo { + private typeParameters: TypeInfo[]; + private typeArguments: TypeInfo[]; + private target: TypeInfo; + + constructor(symbol: Symbol, name: string, typeParameters: TypeInfo[] = []) { + super(symbol, name); + this.typeParameters = typeParameters; + } + + public get hasGenericTypeParameters() { return this.typeParameters && this.typeParameters.length > 0; } + public get isConstructedGenericType() { return this.typeArguments && this.typeArguments.length > 0; } + + public getGenericTypeParameters() { + return this.typeParameters || []; + } + + public getGenericTypeDefinition() { + if (this.target) { + return this.target; + } + + return super.getGenericTypeDefinition(); + } + + public getGenericTypeArguments() { + if (this.isConstructedGenericType) { + return this.typeArguments; + } + + return []; + } + + public makeGenericType(typeArguments: TypeInfo[]) { + let typeParameters = this.getGenericTypeParameters(); + if (typeParameters.length === 0 || typeParameters.length !== typeArguments.length) { + throw new TypeError(); + } + + let target: TypeInfo = this.target || this; + let key = formatTypeInfoKey([target, ...typeArguments]); + let typeInfo = getProperty(typeInfoForTypeReference, key); + if (!typeInfo) { + typeInfo = this.createType(); + typeInfo.members = target.members; + typeInfo.target = target; + typeInfo.typeArguments = typeArguments; + typeInfoForTypeReference[key] = typeInfo; + } + return typeInfo; + } + + public toString(): string { + let text = this.name; + if (this.isConstructedGenericType) { + text += "<" + this.typeArguments.join(", ") + ">"; + } + + return text; + } + + protected abstract createType(): GenericTypeInfo; +} + +class InterfaceInfo extends GenericTypeInfo { + private superTypes: TypeInfo[]; + + public subTypes: TypeInfo[] = []; + + constructor(symbol: Symbol, name: string, typeParameters: TypeInfo[], superTypes: TypeInfo[]) { + super(symbol, name, typeParameters); + this.superTypes = superTypes || []; + + for (let superType of this.superTypes) { + recordSubTypeRelationship(this, superType); + } + } + + public get isInterface() { return true; } + + public getSuperTypes() { + return this.superTypes; + } + + protected createType() { + return new InterfaceInfo(this.symbol, this.name, this.getGenericTypeParameters(), this.getSuperTypes()); + } +} + +class TypeAliasInfo extends GenericTypeInfo { + private aliasedType: TypeInfo; + + constructor(symbol: Symbol, name: string, typeParameters: TypeInfo[], aliasedType: TypeInfo) { + super(symbol, name, typeParameters); + this.aliasedType = aliasedType; + + recordAliasRelationship(this, aliasedType); + } + + public get isTypeAlias() { return true; } + + public getAliasedType() { + return this.aliasedType; + } + + protected createType() { + return new TypeAliasInfo(this.symbol, this.name, this.getGenericTypeParameters(), this.aliasedType); + } +} + +class TypeParameterInfo extends TypeInfo { + private constraint: TypeInfo; + + constructor(symbol: Symbol, name: string, constraint?: TypeInfo) { + super(symbol, name); + this.constraint = constraint; + } + + public get isGenericTypeParameter() { return true; } + + public getConstraint() { + return this.constraint; + } +} + +class UnionTypeInfo extends TypeInfo { + private constituentTypes: TypeInfo[]; + + constructor(constituentTypes: TypeInfo[]) { + super(/*symbol*/ undefined, /*name*/ undefined); + this.constituentTypes = constituentTypes || []; + + for (let constituentType of this.constituentTypes) { + recordUnionRelationship(this, constituentType); + } + } + + public get isUnionType() { return true; } + + public getConstituentTypes() { + return this.constituentTypes.slice(0); + } + + public toString() { + return this.constituentTypes.join(" | "); + } +} + +class OtherTypeInfo extends TypeInfo { + constructor(name: string) { + super(/*symbol*/ undefined, name); + } + + public get isOtherType() { return true; } +} + +export class PropertyInfo implements Annotated { + private annotations: Annotation[]; + private allAnnotations: Annotation[]; + + public containingType: TypeInfo; + public symbol: Symbol; + public name: string; + public propertyType: TypeInfo; + + constructor(containingType: TypeInfo, symbol: Symbol, name: string) { + this.containingType = containingType; + this.symbol = symbol; + this.name = name; + } + + public getOverriddenProperties() { + let overriddenProperties: PropertyInfo[] = []; + for (let superType of this.containingType.getSuperTypes()) { + let overriddenProperty = superType.getProperty(this.name, /*inherited*/ true); + if (overriddenProperty) { + overriddenProperties.push(overriddenProperty); + } + } + + return overriddenProperties; + } + + public getAnnotations(inherited: boolean) { + return inherited ? this.getInheritedAnnotations() : this.getOwnAnnotations(); + } + + public findAllAnnotations(inherited: boolean, match: (annotation: Annotation) => annotation is T): T[] { + return findAllAnnotationsOf(this, inherited, match); + } + + public findFirstAnnotation(inherited: boolean, match: (annotation: Annotation) => annotation is T): T { + return findFirstAnnotationOf(this, inherited, match); + } + + private getOwnAnnotations() { + if (!this.annotations) { + let seen: Map = {}; + this.annotations = []; + for (let annotation of getAnnotations(this.symbol)) { + if (!annotationAllowsMultiple(annotation)) { + if (hasProperty(seen, annotation.name)) { + continue; + } + + seen[annotation.name] = true; + } + + this.annotations.push(annotation); + } + } + + return this.annotations; + } + + private getInheritedAnnotations() { + if (!this.allAnnotations) { + let seen: Map = {}; + this.allAnnotations = []; + for (let annotation of this.getOwnAnnotations()) { + if (!annotationAllowsMultiple(annotation)) { + seen[annotation.name] = true; + } + + this.allAnnotations.push(annotation); + } + + for (let overriddenProperty of this.getOverriddenProperties()) { + for (let annotation of overriddenProperty.getInheritedAnnotations()) { + if (annotationMayBeInherited(annotation)) { + if (!annotationAllowsMultiple(annotation)) { + if (hasProperty(seen, annotation.name)) { + continue; + } + + seen[annotation.name] = true; + } + + this.allAnnotations.push(annotation); + } + } + } + } + + return this.allAnnotations; + } +} + +export class Annotation { + public static inherited = true; + public static allowMultiple = true; + public name: string; + public arguments: any[]; + constructor(_arguments: any[]) { + this.arguments = _arguments; + } + + public static match(annotation: Annotation): boolean { + return annotation instanceof this; + } +} + +function getCompilerOptions() { + let options = ts.getDefaultCompilerOptions(); + options.noResolve = true; + options.noLib = true; + return options; +} + +export function loadSourceFiles(names: string[]) { + symbolToAnnotations.length = 0; + program = ts.createProgram(names, options, host, program); + program.getSourceFile(names[0]); + checker = program.getTypeChecker(); +} + +export function getType(name: string) { + let symbol = resolveQualifiedName(name, SymbolFlags.Type); + return symbol && getDeclaredTypeOfSymbol(symbol); +} + +export function getTypes(ns: string) { + let namespaceSymbol = resolveQualifiedName(ns, SymbolFlags.Namespace); + let typeSymbols = getSymbols(namespaceSymbol.exports, SymbolFlags.Type); + return typeSymbols.map(getDeclaredTypeOfSymbol); +} + +function getGlobalArrayType() { + if (!globalArrayType) { + globalArrayType = new InterfaceInfo(/*symbol*/ undefined, "Array", [ + new TypeParameterInfo(/*symbol*/ undefined, "T") + ], []); + } + return globalArrayType; +} + +export function makeArrayType(elementType: TypeInfo) { + return getGlobalArrayType().makeGenericType([elementType]); +} + +function getDeclaredTypeOfSymbol(symbol: Symbol) { + if (symbol.flags & SymbolFlags.Type) { + let decl = symbol.declarations[0]; + if (isInterfaceDeclaration(decl)) { + return getDeclaredTypeInfoOfInterface(symbol, decl); + } + else if (isTypeAliasDeclaration(decl)) { + return getDeclaredTypeInfoOfTypeAlias(symbol, decl); + } + else if (isTypeParameterDeclaration(decl)) { + return getDeclaredTypeInfoOfTypeParameter(symbol, decl); + } + else { + return getDeclaredTypeInfoOfOtherType(symbol); + } + } + + return undefined; +} + +function getInterfaceExtendsClause(decl: ts.InterfaceDeclaration): ts.ExpressionWithTypeArguments[] { + if (decl.heritageClauses && decl.heritageClauses.length > 0) { + return decl.heritageClauses[0].types; + } + + return []; +} + +function getDeclaredTypeInfoOfInterface(symbol: Symbol, decl: ts.InterfaceDeclaration) { + let typeInfo = typeInfoForSymbol[getSymbolId(symbol)]; + if (!typeInfo) { + let typeParameters: TypeInfo[] = decl.typeParameters ? decl.typeParameters.map(getTypeInfoOfTypeParameter) : []; + let superTypes: TypeInfo[] = getInterfaceExtendsClause(decl).map(getTypeInfoOfTypeNode); + typeInfo = typeInfoForSymbol[getSymbolId(symbol)] = new InterfaceInfo(symbol, symbol.name, typeParameters, superTypes); + fillTypeInfoFromType(typeInfo, checker.getDeclaredTypeOfSymbol(symbol), symbol); + } + return typeInfo; +} + +function getDeclaredTypeInfoOfTypeAlias(symbol: Symbol, decl: ts.TypeAliasDeclaration) { + let typeInfo = typeInfoForSymbol[getSymbolId(symbol)]; + if (!typeInfo) { + let typeParameters: TypeInfo[] = decl.typeParameters ? decl.typeParameters.map(getTypeInfoOfTypeParameter) : []; + let aliasedType = getTypeInfoOfTypeNode(decl.type); + typeInfo = typeInfoForSymbol[getSymbolId(symbol)] = new TypeAliasInfo(symbol, symbol.name, typeParameters, aliasedType); + fillTypeInfoFromType(typeInfo, checker.getDeclaredTypeOfSymbol(symbol), symbol); + } + return typeInfo; +} + +function getDeclaredTypeInfoOfTypeParameter(symbol: Symbol, decl: ts.TypeParameterDeclaration) { + let typeInfo = typeInfoForSymbol[getSymbolId(symbol)]; + if (!typeInfo) { + let constraint = decl.constraint ? getTypeInfoOfTypeNode(decl.constraint) : undefined; + typeInfo = typeInfoForSymbol[getSymbolId(symbol)] = new TypeParameterInfo(symbol, symbol.name, constraint); + } + return typeInfo; +} + +function getDeclaredTypeInfoOfOtherType(symbol: Symbol) { + let typeInfo = typeInfoForSymbol[getSymbolId(symbol)]; + if (!typeInfo) { + typeInfo = typeInfoForSymbol[getSymbolId(symbol)] = new OtherTypeInfo(symbol.name); + fillTypeInfoFromType(typeInfo, checker.getDeclaredTypeOfSymbol(symbol), symbol); + } + return typeInfo; +} + +function getTypeInfoOfProperty(symbol: Symbol): TypeInfo { + if (symbol.flags & SymbolFlags.Property) { + let typeInfo = typeInfoForSymbol[getSymbolId(symbol)]; + if (!typeInfo) { + let decl = symbol.valueDeclaration; + if (isPropertySignature(decl)) { + return getTypeInfoOfTypeNode(decl.type); + } + } + return typeInfo; + } + return undefined; +} + +function getTypeInfoOfTypeParameter(node: ts.TypeParameterDeclaration): TypeInfo { + let symbol = checker.getSymbolAtLocation(node.name); + return getDeclaredTypeOfSymbol(symbol); +} + +function getTypeInfoOfTypeNode(typeNode: ts.TypeNode): TypeInfo { + if (isTypeReferenceNode(typeNode)) { + let symbol = checker.getSymbolAtLocation(typeNode.typeName); + let typeInfo = getDeclaredTypeOfSymbol(symbol); + if (typeNode.typeArguments && typeNode.typeArguments.length) { + let typeArguments = typeNode.typeArguments.map(getTypeInfoOfTypeNode); + typeInfo = typeInfo.makeGenericType(typeArguments); + } + return typeInfo; + } + else if (isExpressionWithTypeArguments(typeNode)) { + let symbol = checker.getSymbolAtLocation(typeNode.expression); + let typeInfo = symbol ? getDeclaredTypeOfSymbol(symbol) : undefined; + if (!typeInfo) { + if (isIdentifier(typeNode.expression) && (typeNode.expression).text === "Array") { + typeInfo = getGlobalArrayType(); + } + else { + typeInfo = getTypeInfoOfOtherType(typeNode.expression.getText().trim()); + } + } + if (typeNode.typeArguments && typeNode.typeArguments.length) { + let typeArguments = typeNode.typeArguments.map(getTypeInfoOfTypeNode); + typeInfo = typeInfo.makeGenericType(typeArguments); + } + return typeInfo; + } + else if (isUnionTypeNode(typeNode)) { + return getTypeInfoOfUnionTypeNode(typeNode); + } + else if (isArrayTypeNode(typeNode)) { + return getTypeInfoOfArrayTypeNode(typeNode); + } + else { + return getTypeInfoOfOtherType(typeNode.getText().trim()); + } +} + +function getTypeInfoOfOtherType(name: string): TypeInfo { + let typeInfo = getProperty(typeInfoForName, name); + if (!typeInfo) { + typeInfo = new OtherTypeInfo(name); + typeInfoForName[name] = typeInfo; + } + return typeInfo; +} + +function getTypeInfoOfArrayTypeNode(typeNode: ts.ArrayTypeNode): TypeInfo { + let elementType = getTypeInfoOfTypeNode(typeNode.elementType); + return makeArrayType(elementType); +} + +function getTypeInfoOfUnionTypeNode(typeNode: ts.UnionTypeNode): TypeInfo { + let constituentTypes = typeNode.types.map(getTypeInfoOfTypeNode); + constituentTypes.sort((a, b) => a.toString().localeCompare(b.toString())); + let key = formatTypeInfoKey(constituentTypes); + let typeInfo: TypeInfo = getProperty(typeInfoForUnion, key); + if (!typeInfo) { + typeInfo = new UnionTypeInfo(constituentTypes); + typeInfoForUnion[key] = typeInfo; + let type = checker.getTypeAtLocation(typeNode); + fillTypeInfoFromType(typeInfo, type, getSymbolOfType(type)); + } + return typeInfo; +} + +function fillTypeInfoFromType(typeInfo: TypeInfo, type: ts.Type, symbol: Symbol) { + for (let member of checker.getPropertiesOfType(type)) { + let propertyInfo: PropertyInfo; + if (member.flags & SymbolFlags.Property) { + if (getSymbolParent(member) === symbol) { + propertyInfo = new PropertyInfo(typeInfo, member, member.name); + propertyInfo.propertyType = getTypeInfoOfProperty(member); + propertyInfoForSymbol[getSymbolId(member)] = propertyInfo; + } + else { + propertyInfo = propertyInfoForSymbol[getSymbolId(member)]; + } + } + + if (propertyInfo) { + typeInfo.members.push(propertyInfo); + } + } +} + +/** + * Gets a symbol with the specified name and meaning from the provided symbol table. + * @param symbols The symbol table from which to retrieve a named symbol. + * @param name The name of the symbol to retrieve. + * @param meaning The meaning of the symbol. + */ +export function getSymbol(symbols: ts.SymbolTable, name: string, meaning: SymbolFlags): Symbol { + if (symbols && meaning && hasProperty(symbols, name)) { + let symbol = symbols[name]; + if (symbol.flags & meaning) { + return symbol; + } + } + + return undefined; +} + +/** + * Gets al symbols with the specified meaning from the provided symbol table. + * @param symbols The symbol table from which to retrieve symbols. + * @param meaning The meaning of each symbol. + */ +export function getSymbols(symbols: ts.SymbolTable, meaning: SymbolFlags) { + let results: Symbol[]; + if (symbols && meaning) { + for (let name in symbols) { + let symbol = getProperty(symbols, name); + if (symbol && symbol.flags & meaning) { + if (!results) { + results = []; + } + results.push(symbol); + } + } + } + return results || []; +} + +export function getQualifiedSymbol(symbolTable: ts.SymbolTable, qualifiedName: string, meaning: SymbolFlags): Symbol { + return getQualifiedSymbolParts(symbolTable, qualifiedName.split("."), meaning); +} + +function getQualifiedSymbolParts(symbolTable: ts.SymbolTable, qualifiedName: string[], meaning: SymbolFlags): Symbol { + if (qualifiedName.length === 1) { + return getSymbol(symbolTable, qualifiedName[0], meaning); + } + + let ns = getSymbol(symbolTable, qualifiedName[0], SymbolFlags.Namespace); + if (ns === undefined) { + return undefined; + } + + for (let i = 1; i < qualifiedName.length - 1; i++) { + ns = getSymbol(ns.exports, qualifiedName[i], SymbolFlags.Namespace); + if (ns === undefined) { + return undefined; + } + } + + return getSymbol(ns.exports, qualifiedName[qualifiedName.length - 1], meaning); +} + +function getSymbolOfType(type: ts.Type): Symbol { + return (type).symbol; +} + +function getSymbolParent(symbol: Symbol): Symbol { + return (symbol).parent; +} + +function getTypeId(type: ts.Type): number { + return (type).id; +} + +function resolveName(location: Node, name: string, meaning: SymbolFlags): Symbol { + let symbols = checker.getSymbolsInScope(location, meaning); + for (let symbol of symbols) { + if (symbol.name === name) { + return symbol; + } + } + + return undefined; +} + +export function resolveQualifiedName(qualifiedName: string, meaning: SymbolFlags): Symbol { + return resolveQualifiedNameParts(/*location*/ undefined, qualifiedName.split("."), meaning); +} + +function resolveEntityName(name: ts.EntityName | ts.Expression): Symbol { + let qualifiedName: string[] = []; + return fillQualifiedName(name, qualifiedName) + ? resolveQualifiedNameParts(name, qualifiedName, SymbolFlags.Type) + : undefined; +} + +function fillQualifiedName(name: ts.EntityName | ts.Expression, qualifiedName: string[]): boolean { + if (isIdentifier(name)) { + qualifiedName.push(name.text); + return true; + } + else if (isQualifiedName(name)) { + return fillQualifiedName(name.left, qualifiedName) + && fillQualifiedName(name.right, qualifiedName); + } + else if (isPropertyAccessExpression(name)) { + return fillQualifiedName(name.expression, qualifiedName) + && fillQualifiedName(name.name, qualifiedName); + } + return false; +} + + +function resolveQualifiedNameParts(location: Node, qualifiedName: string[], meaning: SymbolFlags): Symbol { + if (qualifiedName.length === 1) { + return resolveName(location, qualifiedName[0], meaning); + } + + let ns = resolveName(location, qualifiedName[0], SymbolFlags.Namespace); + if (ns === undefined) { + return undefined; + } + + for (let i = 1; i < qualifiedName.length - 1; i++) { + ns = getSymbol(ns.exports, qualifiedName[i], SymbolFlags.Namespace); + if (ns === undefined) { + return undefined; + } + } + + return getSymbol(ns.exports, qualifiedName[qualifiedName.length - 1], meaning); +} + +export function getLiteralValue(location: Node, expr: ts.Expression): any { + switch (expr.kind) { + case SyntaxKind.TrueKeyword: + return true; + + case SyntaxKind.FalseKeyword: + return false; + + case SyntaxKind.NullKeyword: + return null; + + case SyntaxKind.VoidExpression: + return undefined; + + case SyntaxKind.StringLiteral: + return (expr).text; + + case SyntaxKind.NoSubstitutionTemplateLiteral: + return (expr).text; + + case SyntaxKind.NumericLiteral: + return Number((expr).text); + + case SyntaxKind.PropertyAccessExpression: + return getEnumLiteralValue(location, expr.getText()); + + case SyntaxKind.ArrayLiteralExpression: + return getArrayLiteralValue(location, expr); + + case SyntaxKind.ObjectLiteralExpression: + return getObjectLiteralValue(location, expr); + } +} + +/** + * Gets the value of the specified enum. + * @param location The node at which to resolve the name. + * @param name The name of the enum member. + */ +function getEnumLiteralValue(location: Node, name: string): EnumValue { + let qn = name.split("."); + if (qn.length === 1) { + return undefined; + } + + let container = resolveQualifiedNameParts(location, qn.slice(0, qn.length - 1), SymbolFlags.Enum); + if (!container) { + return undefined; + } + + let symbol = getSymbol(container.exports, qn[qn.length - 1], SymbolFlags.EnumMember); + if (!symbol) { + return undefined; + } + + let value = checker.getConstantValue(symbol.declarations[0]); + return { symbol, value }; +} + +function getArrayLiteralValue(location: Node, expr: ts.ArrayLiteralExpression) { + let values: any[] = []; + for (let element of expr.elements) { + let value = getLiteralValue(location, element); + values.push(value); + } + return values; +} + +function getObjectLiteralValue(location: Node, expr: ts.ObjectLiteralExpression) { + let obj: Map = {}; + for (let element of expr.properties) { + if (isPropertyAssignment(element)) { + let name = element.name; + if (isIdentifier(name)) { + obj[name.text] = getLiteralValue(location, element.initializer); + } + } + } + return obj; +} + +export interface Annotated { + getAnnotations(inherited: boolean): Annotation[]; + findAllAnnotations(inherited: boolean, match: (annotation: Annotation) => annotation is T): T[]; + findFirstAnnotation(inherited: boolean, match: (annotation: Annotation) => annotation is T): T; +} + +function formatTypeInfoKey(types: TypeInfo[]) { + return types.map(type => type.id).join("-"); +} + +function recordSubTypeRelationship(subType: TypeInfo, superType: TypeInfo) { + let subTypes = subTypeRelationships[superType.id] || (subTypeRelationships[superType.id] = []); + subTypes.push(subType); +} + +function recordAliasRelationship(aliasType: TypeInfo, aliasedType: TypeInfo) { + let aliasTypes = aliasRelationships[aliasedType.id] || (aliasRelationships[aliasedType.id] = []); + aliasTypes.push(aliasType); +} + +function recordUnionRelationship(unionType: TypeInfo, constituentType: TypeInfo) { + let unionTypes = unionRelationships[constituentType.id] || (unionRelationships[constituentType.id] = []); + unionTypes.push(unionType); +} + +export function annotation(name: string, options?: { inherited?: boolean; allowMultiple?: boolean; }) { + return function(constructor: T) { + symbolToAnnotations.length = 0; + let inherited = options && "inherited" in options ? options.inherited : false; + let allowMultiple = options && "allowMultiple" in options ? options.allowMultiple : true; + annotationConstructors[name] = { constructor, inherited, allowMultiple, }; + return constructor; + } +} + +function annotationMayBeInherited(annotation: Annotation) { + let entry = getProperty(annotationConstructors, annotation.name); + return entry ? entry.inherited : true; +} + +function annotationAllowsMultiple(annotation: Annotation) { + let entry = getProperty(annotationConstructors, annotation.name); + return entry ? entry.allowMultiple : true; +} + +export function getAnnotations(symbol: Symbol): Annotation[] { + let annotations = symbolToAnnotations[getSymbolId(symbol)]; + if (annotations) { + return annotations; + } + + let seen: Map = {}; + annotations = []; + for (let decl of symbol.declarations) { + let sourceFile = getSourceFileOfNode(decl); + let leadingCommentRanges = ts.getLeadingCommentRanges(sourceFile.text, decl.pos); + if (leadingCommentRanges) { + for (let range of leadingCommentRanges) { + parseAnnotations(decl, range, annotations, seen); + } + } + } + return symbolToAnnotations[getSymbolId(symbol)] = annotations; +} + +export function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation; +export function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation; +export function findFirstAnnotation(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation { + for (let annotation of getAnnotations(symbol)) { + if (match(annotation)) { + return annotation; + } + } + return undefined; +} + +export function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation[]; +export function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[]; +export function findAllAnnotations(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[] { + let annotations: TAnnotation[]; + for (let annotation of getAnnotations(symbol)) { + if (match(annotation)) { + if (!annotations) { + annotations = []; + } + annotations.push(annotation); + } + } + return annotations || []; +} + +function findFirstAnnotationOf(info: Annotated, inherited: boolean, match: (annotation: Annotation) => annotation is T): T { + for (let annotation of info.getAnnotations(inherited)) { + if (match(annotation)) { + return annotation; + } + } + return undefined; +} + +function findAllAnnotationsOf(info: Annotated, inherited: boolean, match: (annotation: Annotation) => annotation is T): T[] { + let annotations: T[] = []; + for (let annotation of info.getAnnotations(inherited)) { + if (match(annotation)) { + annotations.push(annotation); + } + } + return annotations; +} + +function parseAnnotations(location: Node, range: ts.CommentRange, annotations: Annotation[], seen: Map) { + let sourceFile = getSourceFileOfNode(location); + let text = sourceFile.text; + let comment = text.substring(range.pos, range.end); + let annotationMatch: RegExpExecArray; + while (annotationMatch = annotationPattern.exec(comment)) { + let annotation = parseAnnotation(location, annotationMatch[1]); + if (annotation) { + let entry = getProperty(annotationConstructors, annotation.name); + if (entry && !entry.allowMultiple && hasProperty(seen, annotation.name)) { + continue; + } + + if (annotation) { + annotations.push(annotation); + } + } + } +} + +function parseAnnotation(location: Node, annotationSource: string) { + let evalSourceFile = ts.createSourceFile("eval.ts", annotationSource, ts.ScriptTarget.Latest, true); + let statements = evalSourceFile.statements; + if (statements.length === 0) { + return undefined; + } + + let stmt = statements[0]; + if (stmt.kind !== SyntaxKind.ExpressionStatement) { + return undefined; + } + + let expr = (stmt).expression; + if (isIdentifier(expr)) { + return createAnnotation(expr.text, []); + } + else if (isCallExpression(expr)) { + if (expr.expression.kind !== SyntaxKind.Identifier) { + return undefined; + } + + let _arguments: any[] = []; + for (let argument of expr.arguments) { + _arguments.push(getLiteralValue(location, argument)); + } + + return createAnnotation((expr.expression).text, _arguments); + } + else { + return undefined; + } +} + +function createAnnotation(name: string, _arguments: any[]): Annotation { + let entry = getProperty(annotationConstructors, name); + let annotation = entry ? new entry.constructor(_arguments) : new Annotation(_arguments); + annotation.name = name; + return annotation; +} + +function isTypeReferenceNode(node: Node): node is ts.TypeReferenceNode { + return node ? node.kind === SyntaxKind.TypeReference : false; +} + +function isUnionTypeNode(node: Node): node is ts.UnionTypeNode { + return node ? node.kind === SyntaxKind.UnionType : false; +} + +function isArrayTypeNode(node: Node): node is ts.ArrayTypeNode { + return node ? node.kind === SyntaxKind.ArrayType : false; +} + +function isInterfaceDeclaration(node: Node): node is ts.InterfaceDeclaration { + return node ? node.kind === SyntaxKind.InterfaceDeclaration : false; +} + +function isTypeAliasDeclaration(node: Node): node is ts.TypeAliasDeclaration { + return node ? node.kind === SyntaxKind.TypeAliasDeclaration : false; +} + +function isTypeParameterDeclaration(node: Node): node is ts.TypeParameterDeclaration { + return node ? node.kind === SyntaxKind.TypeParameter : false; +} + +function isExpressionWithTypeArguments(node: Node): node is ts.ExpressionWithTypeArguments { + return node ? node.kind === SyntaxKind.ExpressionWithTypeArguments : false; +} + +function isPropertySignature(node: Node): node is ts.PropertyDeclaration { + return node && node.kind === SyntaxKind.PropertySignature; +} + +function isPropertyAssignment(node: Node): node is ts.PropertyAssignment { + return node && node.kind === SyntaxKind.PropertyAssignment; +} + +function isIdentifier(node: Node): node is ts.Identifier { + return node && node.kind === SyntaxKind.Identifier; +} + +function isCallExpression(node: Node): node is ts.CallExpression { + return node && node.kind === SyntaxKind.CallExpression; +} + +function isQualifiedName(node: Node): node is ts.QualifiedName { + return node && node.kind === SyntaxKind.QualifiedName; +} + +function isPropertyAccessExpression(node: Node): node is ts.PropertyAccessExpression { + return node && node.kind === SyntaxKind.PropertyAccessExpression; +} + +function getSourceFileOfNode(node: Node): ts.SourceFile { + while (node && node.kind !== SyntaxKind.SourceFile) { + node = node.parent; + } + return node; +} diff --git a/scripts/processTypes/typescript-internal.d.ts b/scripts/processTypes/typescript-internal.d.ts new file mode 100644 index 00000000000..900737517e4 --- /dev/null +++ b/scripts/processTypes/typescript-internal.d.ts @@ -0,0 +1,4 @@ +/// +import { Symbol } from "typescript"; +export * from "typescript"; +export declare function getSymbolId(symbol: Symbol): number; \ No newline at end of file diff --git a/scripts/processTypes/typescript-internal.js b/scripts/processTypes/typescript-internal.js new file mode 100644 index 00000000000..bba92f076e1 --- /dev/null +++ b/scripts/processTypes/typescript-internal.js @@ -0,0 +1 @@ +module.exports = require("../../../lib/typescript"); \ No newline at end of file diff --git a/scripts/processTypes/utilities.ts b/scripts/processTypes/utilities.ts new file mode 100644 index 00000000000..0f296871f18 --- /dev/null +++ b/scripts/processTypes/utilities.ts @@ -0,0 +1,49 @@ +import { Map } from "./typescript-internal"; + +let hasOwnProperty = Object.prototype.hasOwnProperty; + +export function hasProperty(map: Map, key: string): boolean { + return hasOwnProperty.call(map, key); +} + +export function getProperty(map: Map, key: string): T { + return hasOwnProperty.call(map, key) ? map[key] : undefined; +} + +export let directorySeparator = "/"; + +export function getRootLength(path: string): number { + if (path.charAt(0) === directorySeparator) { + if (path.charAt(1) !== directorySeparator) return 1; + let p1 = path.indexOf("/", 2); + if (p1 < 0) return 2; + let p2 = path.indexOf("/", p1 + 1); + if (p2 < 0) return p1 + 1; + return p2 + 1; + } + if (path.charAt(1) === ":") { + if (path.charAt(2) === directorySeparator) return 3; + return 2; + } + // Per RFC 1738 'file' URI schema has the shape file:/// + // if is omitted then it is assumed that host value is 'localhost', + // however slash after the omitted is not removed. + // file:///folder1/file1 - this is a correct URI + // file://folder2/file2 - this is an incorrect URI + if (path.lastIndexOf("file:///", 0) === 0) { + return "file:///".length; + } + let idx = path.indexOf("://"); + if (idx !== -1) { + return idx + "://".length; + } + return 0; +} + +export function combinePaths(path1: string, path2: string) { + if (!(path1 && path1.length)) return path2; + if (!(path2 && path2.length)) return path1; + if (getRootLength(path2) !== 0) return path2; + if (path1.charAt(path1.length - 1) === directorySeparator) return path1 + path2; + return path1 + directorySeparator + path2; +} \ No newline at end of file diff --git a/scripts/typescript-internal.d.ts b/scripts/typescript-internal.d.ts deleted file mode 100644 index 6d81d4113dc..00000000000 --- a/scripts/typescript-internal.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/// -import { SourceFile, Node, Map, Symbol } from "typescript"; - -export * from "typescript"; - -export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(sourceFile: SourceFile, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; - getText(): string; - rawWrite(s: string): void; - writeLiteral(s: string): void; - getTextPos(): number; - getLine(): number; - getColumn(): number; - getIndent(): number; -} - -export declare function computeLineStarts(text: string): number[]; -export declare function createTextWriter(newLine: String): EmitTextWriter; -export declare function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string; -export declare function combinePaths(path1: string, path2: string): string; -export declare function map(array: T[], f: (x: T) => U): U[]; -export declare function hasProperty(map: Map, key: string): boolean; -export declare function getProperty(map: Map, key: string): T; -export declare function getNodeId(node: Node): number; -export declare function getSymbolId(symbol: Symbol): number; \ No newline at end of file diff --git a/scripts/typescript-internal.js b/scripts/typescript-internal.js deleted file mode 100644 index 709e3ce7462..00000000000 --- a/scripts/typescript-internal.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("../lib/typescript"); \ No newline at end of file diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d3e67eab210..276a7ae9faa 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -82,7 +82,7 @@ namespace ts { bindSourceFileWorker(file); bindTime += new Date().getTime() - start; } - + // function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) { // return 0; // } @@ -102,7 +102,7 @@ namespace ts { let Symbol = objectAllocator.getSymbolConstructor(); let classifiableNames: Map = {}; let subtreeTransformFlags: TransformFlags; - let skipTransformFlagAggregation: boolean; + let skipTransformFlagAggregation = isDeclarationFile(file); if (!file.locals) { bind(file); @@ -788,7 +788,7 @@ namespace ts { // However, not all symbols will end up in any of these tables. 'Anonymous' symbols // (like TypeLiterals for example) will not be put in any table. bindWorker(node); - + // Then we recurse into the children of the node to bind them as well. For certain // symbols we do specialized work when we recurse. For example, we'll keep track of // the current 'container' node when it changes. This helps us know which symbol table @@ -797,13 +797,13 @@ namespace ts { inStrictMode = savedInStrictMode; } - + function aggregateTransformFlagsIfNeededAnd(cbNode: (node: Node) => T, node: Node): T { - return node.transformFlags !== undefined + return node.transformFlags !== undefined ? skipTransformFlagAggregationAnd(cbNode, node) : aggregateTransformFlagsAnd(cbNode, node); } - + function skipTransformFlagAggregationAnd(cbNode: (node: Node) => T, node: Node): T { if (!skipTransformFlagAggregation) { skipTransformFlagAggregation = true; @@ -811,10 +811,10 @@ namespace ts { skipTransformFlagAggregation = false; return result; } - + return cbNode(node); } - + function aggregateTransformFlagsAnd(cbNode: (node: Node) => T, node: Node): T { if (!skipTransformFlagAggregation) { let savedSubtreeTransformFlags = subtreeTransformFlags; @@ -823,10 +823,10 @@ namespace ts { subtreeTransformFlags = savedSubtreeTransformFlags | (computeTransformFlagsForNode(node, subtreeTransformFlags) & ~TransformFlags.NodeExcludes); return result; } - + return cbNode(node); } - + function updateStrictMode(node: Node) { switch (node.kind) { case SyntaxKind.SourceFile: @@ -1102,4 +1102,376 @@ namespace ts { : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } } + + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) { + Debug.assert((subtreeFlags & TransformFlags.NodeExcludes) == 0, "Subtree includes a `ThisNode...` flag."); + + // Mark transformations needed for each node + let transformFlags: TransformFlags; + let excludeFlags: TransformFlags; + let kind = node.kind; + switch (kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.AwaitExpression: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + // These nodes are TypeScript syntax. + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxText: + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxExpression: + // These nodes are Jsx syntax. + transformFlags |= TransformFlags.ThisNodeIsJsx; + break; + + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.TemplateExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.YieldExpression: + // These nodes are ES6 syntax. + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.ComputedPropertyName: + // Even though computed property names are ES6, we don't treat them as such. + // This is so that they can flow through PropertyName transforms unaffected. + // Instead, we mark the container as ES6, so that it can properly handle the transform. + transformFlags |= TransformFlags.ContainerIsES6; + break; + + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.SuperKeyword: + // These nodes are ES6 syntax, and mark their immediate containers as ES6. + transformFlags |= TransformFlags.ThisNodeIsES6 | TransformFlags.ContainerIsES6; + break; + + case SyntaxKind.ThisKeyword: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= TransformFlags.ContainsLexicalThis; + break; + + // case SyntaxKind.BreakStatement: + // case SyntaxKind.ContinueStatement: + // case SyntaxKind.ReturnStatement: + // return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsCompletionStatement; + + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + // These nodes are ES6 syntax. + transformFlags |= TransformFlags.ThisNodeIsES6; + break; + + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + // If the subtree has marked the container as ES6, then these nodes are ES6. + if (subtreeFlags & TransformFlags.ContainerIsES6) { + excludeFlags = TransformFlags.ContainerIsES6; + transformFlags |= TransformFlags.ES6; + } + + break; + + case SyntaxKind.PropertyAssignment: + // If the name of the assignment is a ComputedPropertyName, we need to mark the container + // as ES6 so that it is picked up by the transformer. + if (isComputedPropertyName((node).name)) { + transformFlags |= TransformFlags.ContainerIsES6; + } + break; + + case SyntaxKind.Decorator: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + transformFlags |= TransformFlags.ContainerIsTypeScript; + break; + + case SyntaxKind.ModuleDeclaration: + // This node is TypeScript syntax, and excludes markers that should not escape the module scope. + excludeFlags = TransformFlags.ModuleScopeExcludes; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + // case SyntaxKind.ArrayLiteralExpression: + // case SyntaxKind.CallExpression: + // return (node.transformFlags = subtreeFlags) + // & ~(node.excludeTransformFlags = TransformFlags.CallOrArrayLiteralExcludes); + + case SyntaxKind.ExpressionStatement: + if (node.flags & NodeFlags.GeneratedSuper) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + + case SyntaxKind.BinaryExpression: + // Destructuring assignments are ES6 syntax. + if (isDestructuringAssignment(node)) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.TypeReference: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.PropertySignature: + // Types and signatures are TypeScript syntax, and exclude all other facts. + excludeFlags = TransformFlags.TypeExcludes; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + break; + + case SyntaxKind.PropertyDeclaration: + // Property declarations are TypeScript syntax. + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + + // If the declration has an initializer, we must mark the container as being TypeScript syntax. + if ((node).initializer) { + transformFlags |= TransformFlags.ContainerIsTypeScript; + } + + break; + + case SyntaxKind.Parameter: + // If the parameter has a question token, then it is TypeScript syntax. + if ((node).questionToken) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if ((node).flags & NodeFlags.AccessibilityModifier) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainerIsTypeScript; + } + + // If a parameter has a dotDotDot token, then it is ES6 syntax. + if ((node).dotDotDotToken) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + // If a parameter has an initializer or a binding pattern, then it is ES6 syntax and its container + // must emit default value assignments or parameter destructuring downlevel. + if ((node).initializer || isBindingPattern((node).name)) { + transformFlags |= TransformFlags.ThisNodeIsES6 | TransformFlags.ContainsDefaultValueAssignments; + } + + break; + + case SyntaxKind.ArrowFunction: + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + excludeFlags = TransformFlags.ArrowFunctionExcludes; + transformFlags = TransformFlags.ThisNodeIsES6; + + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & TransformFlags.ContainsLexicalThis) { + transformFlags |= TransformFlags.ContainsCapturedLexicalThis; + } + + // If an ArrowFunction is marked async, or its subtree has marked the container as being + // TypeScript syntax, then the node is TypeScript Syntax. + if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.FunctionExpression: + // A FunctionExpression excludes markers that should not escape the scope of a FunctionExpression. + excludeFlags = TransformFlags.FunctionDeclarationOrExpressionExcludes; + + // If a FunctionExpression contains an asterisk token, or its subtree has marked the container + // as needing to capture the lexical this, then this node is ES6 syntax. + if ((node).asteriskToken || transformFlags & TransformFlags.ContainsCapturedLexicalThis) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + // If a FunctionExpression is async, or its subtree has marked the container + // as TypeScript, then this node is TypeScript syntax. + if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.FunctionDeclaration: + // A FunctionDeclaration excludes markers that should not escape the scope of a FunctionDeclaration. + excludeFlags = TransformFlags.FunctionDeclarationOrExpressionExcludes; + + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + if (!(node).body) { + transformFlags = TransformFlags.ThisNodeIsTypeScript; + break; + } + + // transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; + + // If a FunctionDeclaration has an asterisk token, is exported, or its + // subtree has marked the container as needing to capture the lexical `this`, + // then this node is ES6 syntax. + if ((node).asteriskToken + || node.flags & NodeFlags.Export + || subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + // If a FunctionDeclaration is async, or its subtree has marked the container + // as TypeScript, then this node is TypeScript syntax. + if (node.flags & NodeFlags.Async || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.VariableDeclarationList: + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + + // transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; + if (node.flags & (NodeFlags.Let | NodeFlags.Const)) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + + case SyntaxKind.VariableStatement: + // If a VariableStatement is exported, then it is ES6 syntax. + if (node.flags & NodeFlags.Export) { + transformFlags |= TransformFlags.ThisNodeIsES6; + } + + break; + + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + // Class declarations and expressions are ES6 syntax, and exclude markers that should + // not escape the scope of a class. + excludeFlags = TransformFlags.ClassDeclarationOrExpressionExcludes; + transformFlags = TransformFlags.ThisNodeIsES6; + + // If the subtree has marked that the container is TypeScript, then this + // node is TypeScript syntax. + if (subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.HeritageClause: + transformFlags |= TransformFlags.ThisNodeIsES6; + + if ((node).token !== SyntaxKind.ExtendsKeyword || (node).types.length > 1) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.ExpressionWithTypeArguments: + transformFlags |= TransformFlags.ThisNodeIsES6; + + if ((node).typeArguments) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.Constructor: + excludeFlags = TransformFlags.ConstructorExcludes; + transformFlags |= TransformFlags.ThisNodeIsES6; + + if (!(node).body) { + transformFlags = TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.MethodDeclaration: + excludeFlags = TransformFlags.MethodDeclarationExcludes; + transformFlags |= TransformFlags.ThisNodeIsES6; + + if (!(node).body) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + if (node.flags & (NodeFlags.Async | NodeFlags.Abstract) || subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + excludeFlags = TransformFlags.GetOrSetAccessorExcludes; + if (subtreeFlags & TransformFlags.ContainerIsTypeScript) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + // case SyntaxKind.ImportDeclaration: + // case SyntaxKind.ExportDeclaration: + // // Even though these are ES Syntax, we treat them as TypeScript Syntax to support + // // AMD/SystemJS/etc. + // transformFlags |= TransformFlags.ThisNodeIsTypeScript; + // break; + + case SyntaxKind.ImportEqualsDeclaration: + // An ImportEqualsDeclaration with a namespace reference is TypeScript. + if (!isExternalModuleImportEqualsDeclaration(node)) { + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + + // case SyntaxKind.ExportAssignment: + // // An ExportAssignment that is an `export =` will be + // // handled by the emitter and not the transformer. + // if (!(node).isExportEquals) { + // transformFlags |= TransformFlags.ThisNodeIsES6; + // } + + // break; + + default: + if (SyntaxKind.FirstTypeNode <= kind && kind <= SyntaxKind.LastTypeNode) { + excludeFlags = TransformFlags.TypeExcludes; + transformFlags |= TransformFlags.ThisNodeIsTypeScript; + } + + break; + } + + return (node.transformFlags = subtreeFlags | transformFlags) + & ~(node.excludeTransformFlags = excludeFlags); + } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eadc0442b91..6ee46a9389e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -167,6 +167,7 @@ namespace ts { let emitParam = false; let emitAwaiter = false; let emitGenerator = false; + let emitExportStar = false; let resolutionTargets: TypeSystemEntity[] = []; let resolutionResults: boolean[] = []; @@ -1398,7 +1399,7 @@ namespace ts { return true; } } - + function isEntityNameOrExpression(node: Node): node is EntityName | Expression { return isEntityName(node) || isExpressionNode(node); } @@ -2209,7 +2210,7 @@ namespace ts { /** * Push an entry on the type resolution stack. If an entry with the given target and the given property name - * is already on the stack, and no entries in between already have a type, then a circularity has occurred. + * is already on the stack, and no entries in between already have a type, then a circularity has occurred. * In this case, the result values of the existing entry and all entries pushed after it are changed to false, * and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned. * In order to see if the same query has already been done before, the target object and the propertyName both @@ -2379,7 +2380,7 @@ namespace ts { if (isBindingPattern(declaration.parent)) { return getTypeForBindingElement(declaration); } - + // Use type from type annotation if one is present if (declaration.type) { return getTypeFromTypeNode(declaration.type); @@ -2400,12 +2401,12 @@ namespace ts { return type; } } - + // Use the type of the initializer expression if one is present if (declaration.initializer) { return checkExpressionCached(declaration.initializer); } - + // If it is a short-hand property assignment, use the type of the identifier if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) { return checkIdentifier(declaration.name); @@ -2500,10 +2501,10 @@ namespace ts { // tools see the actual type. return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type; } - + // Rest parameters default to type any[], other parameters default to type any type = declaration.dotDotDotToken ? anyArrayType : anyType; - + // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors && compilerOptions.noImplicitAny) { let root = getRootDeclaration(declaration); @@ -4345,7 +4346,7 @@ namespace ts { } return t; }; - + mapper.context = context; return mapper; } @@ -5079,9 +5080,9 @@ namespace ts { if (kind === SignatureKind.Construct) { // Only want to compare the construct signatures for abstractness guarantees. - + // Because the "abstractness" of a class is the same across all construct signatures - // (internally we are checking the corresponding declaration), it is enough to perform + // (internally we are checking the corresponding declaration), it is enough to perform // the check and report an error once over all pairs of source and target construct signatures. // // sourceSig and targetSig are (possibly) undefined. @@ -6248,7 +6249,7 @@ namespace ts { return getUnionType(assignableConstituents); } } - + if (isTypeAssignableTo(narrowedTypeCandidate, originalType)) { // Narrow to the target type if it's assignable to the current type return narrowedTypeCandidate; @@ -6475,46 +6476,46 @@ namespace ts { let classType = classDeclaration && getDeclaredTypeOfSymbol(getSymbolOfNode(classDeclaration)); let baseClassType = classType && getBaseTypes(classType)[0]; - let container = getSuperContainer(node, /*includeFunctions*/ true); + let container = getSuperContainer(node, /*includeFunctions*/ true); let needToCaptureLexicalThis = false; - if (!isCallExpression) { - // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting + if (!isCallExpression) { + // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting while (container && container.kind === SyntaxKind.ArrowFunction) { container = getSuperContainer(container, /*includeFunctions*/ true); needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6; } } - + let canUseSuperExpression = isLegalUsageOfSuperExpression(container); let nodeCheckFlag: NodeCheckFlags = 0; - - // always set NodeCheckFlags for 'super' expression node - if (canUseSuperExpression) { + + // always set NodeCheckFlags for 'super' expression node + if (canUseSuperExpression) { if ((container.flags & NodeFlags.Static) || isCallExpression) { nodeCheckFlag = NodeCheckFlags.SuperStatic; } else { nodeCheckFlag = NodeCheckFlags.SuperInstance; } - + getNodeLinks(node).flags |= nodeCheckFlag; - + if (needToCaptureLexicalThis) { // call expressions are allowed only in constructors so they should always capture correct 'this' // super property access expressions can also appear in arrow functions - // in this case they should also use correct lexical this captureLexicalThis(node.parent, container); - } + } } - + if (!baseClassType) { if (!classDeclaration || !getClassExtendsHeritageClauseElement(classDeclaration)) { error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); } - return unknownType; + return unknownType; } - + if (!canUseSuperExpression) { if (container && container.kind === SyntaxKind.ComputedPropertyName) { error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); @@ -6525,20 +6526,20 @@ namespace ts { else { error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); } - + return unknownType; } - + if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) { // issue custom error message for super property access in constructor arguments (to be aligned with old compiler) error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments); return unknownType; } - + return nodeCheckFlag === NodeCheckFlags.SuperStatic ? getBaseConstructorTypeOfClass(classType) : baseClassType; - + function isLegalUsageOfSuperExpression(container: Node): boolean { if (!container) { return false; @@ -6574,9 +6575,9 @@ namespace ts { } } } - + return false; - } + } } // Return contextual type of parameter or undefined if no contextual type is available @@ -9465,7 +9466,7 @@ namespace ts { return type; } - function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) { + function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); let isAsync = isAsyncFunctionLike(node); @@ -10639,7 +10640,7 @@ namespace ts { } if (!superCallStatement) { error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties); - } + } else { // In such a required super call, it is a compile-time error for argument expressions to reference this. markThisReferencesAsErrors(superCallStatement.expression); @@ -11078,7 +11079,7 @@ namespace ts { // Spaces for anyting not declared a 'default export'. let nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces; - + let commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces; let commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces; @@ -11086,7 +11087,7 @@ namespace ts { // declaration spaces for exported and non-exported declarations intersect for (let d of symbol.declarations) { let declarationSpaces = getDeclarationSpaces(d); - + // Only error on the declarations that conributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { error(d.name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(d.name)); @@ -13284,7 +13285,7 @@ namespace ts { Debug.assert(node.kind === SyntaxKind.Identifier); return node; } - + function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { let moduleName = getExternalModuleName(node); if (!nodeIsMissing(moduleName) && moduleName.kind !== SyntaxKind.StringLiteral) { @@ -13421,6 +13422,8 @@ namespace ts { if (moduleSymbol && moduleSymbol.exports["export="]) { error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } + + emitExportStar = true; } } } @@ -13770,6 +13773,9 @@ namespace ts { emitExtends = false; emitDecorate = false; emitParam = false; + emitAwaiter = false; + emitGenerator = false; + emitExportStar = false; potentialThisCollisions.length = 0; forEach(node.statements, checkSourceElement); @@ -13804,6 +13810,10 @@ namespace ts { links.flags |= NodeCheckFlags.EmitGenerator; } + if (emitExportStar) { + links.flags |= NodeCheckFlags.EmitExportStar; + } + links.flags |= NodeCheckFlags.TypeChecked; } } @@ -13897,7 +13907,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: // If we didn't come from static member of class or interface, - // add the type parameters into the symbol table + // add the type parameters into the symbol table // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. if (!(memberFlags & NodeFlags.Static)) { @@ -13911,11 +13921,11 @@ namespace ts { } break; } - + if (introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - + memberFlags = location.flags; location = location.parent; } @@ -14392,9 +14402,9 @@ namespace ts { } // const enums and modules that contain only const enums are not considered values from the emit perespective // unless 'preserveConstEnums' option is set to true - return target !== unknownSymbol && - target && - target.flags & SymbolFlags.Value && + return target !== unknownSymbol && + target && + target.flags & SymbolFlags.Value && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target)); } @@ -14448,7 +14458,7 @@ 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); } @@ -14473,7 +14483,7 @@ namespace ts { function isFunctionType(type: Type): boolean { return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - + function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. let valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true); @@ -14486,7 +14496,7 @@ namespace ts { let typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true); // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { - return TypeReferenceSerializationKind.ObjectType; + return TypeReferenceSerializationKind.ObjectType; } let type = getDeclaredTypeOfSymbol(typeSymbol); if (type === unknownType) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c58253390f4..ff173b41295 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -52,7 +52,7 @@ namespace ts { function normalizeKey(key: string) { return getCanonicalFileName(normalizeSlashes(key)); } - + function clear() { files = {}; } @@ -129,14 +129,14 @@ 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; } } @@ -189,7 +189,7 @@ namespace ts { } } } - + export function trimArray(array: T[]): T[] { let result: T[]; if (array) { @@ -202,22 +202,34 @@ namespace ts { } return result; } - + export function skip(array: T[], count: number) { if (array) { - return count === 0 ? array : array.slice(count); + return count === 0 ? array : array.slice(count); } return undefined; } - + export function take(array: T[], count: number) { if (array) { - return count === array.length ? array : array.slice(0, count); + return count >= array.length ? array : array.slice(0, count); } - + return undefined; } - + + export function takeWhile(array: T[], callbackfn: (item: T) => boolean): T[] { + if (array) { + for (let i = 0; i < array.length; i++) { + if (!callbackfn(array[i])) { + return array.slice(0, i); + } + } + return array.slice(0); + } + return undefined; + } + export function append(to: T[], ...values: T[]): T[] { let result: T[]; if (to) { @@ -242,7 +254,7 @@ namespace ts { } return true; } - + /** * Returns the first element of an array if non-empty, undefined otherwise. */ @@ -378,6 +390,16 @@ namespace ts { return result; } + export function assign(target: Map, source: Map): Map { + if (!target) { + target = {}; + } + for (let id in source) { + target[id] = source[id]; + } + return target; + } + export function forEachValue(map: Map, callback: (value: T) => U): U { let result: U; for (let id in map) { @@ -883,22 +905,22 @@ namespace ts { let parent = getParent(); return parent ? parent.parent : undefined; } - + /** Gets the parent of the current node, without moving the navigator. */ function getParent() { return currentNode ? currentNode.parent : undefined; } - + /** Gets the current node. */ function getNode() { return currentNode; } - + /** Gets the SyntaxKind for the current node. */ function getKind() { return currentNode ? currentNode.kind : undefined; } - + /** Navigates to the parent of the current node if it has one. */ function moveToParent(): boolean { let parent = getParent(); @@ -906,15 +928,15 @@ namespace ts { currentNode = parent; return true; } - + return false; } - + /** Creates a new ParentNavigator from the current node. */ function createParentNavigator() { return ts.createParentNavigator(currentNode); } - + return { getGrandparent, getParent, @@ -924,7 +946,7 @@ namespace ts { createParentNavigator, }; } - + /** * Creates a node stack used to maintain parent relationships without parent pointers. */ @@ -934,27 +956,27 @@ namespace ts { let rootNode: Node; let parentNode: Node; let currentNode: Node; - + /** Gets the node two steps back from the top of the stack. */ function getGrandparent() { return peekNode(2); } - + /** Gets the node one step back from the top of the stack. */ function getParent() { return parentNode; } - + /** Gets the node at the top of the stack. */ function getNode() { return currentNode; } - + /** Gets the SyntaxKind for the node at the top of the stack. */ function getKind() { return currentNode ? currentNode.kind : undefined; } - + /** Pushes a node onto the stack. */ function pushNode(node: Node): void { stackSize++; @@ -967,17 +989,17 @@ namespace ts { parentNode = currentNode; currentNode = node; } - + /** Pushes a node onto the stack if it is not already at the top of the stack. */ function tryPushNode(node: Node): boolean { if (currentNode !== node) { return false; } - + pushNode(node); return true; } - + /** Pops the top node from the stack. */ function popNode(): void { currentNode = parentNode; @@ -987,12 +1009,12 @@ namespace ts { rootNode = undefined; } } - + /** Replaces the node at the top of the stack. */ function setNode(node: Node): void { currentNode = node; } - + /** Peeks at a node a specified number of steps back from the top of the stack. */ function peekNode(stackOffset: number): Node { switch (stackOffset) { @@ -1018,60 +1040,60 @@ namespace ts { } return undefined; } - + /** Creates a parent navigator from the top of the stack. */ function createParentNavigator() { return createParentNavigatorFromStackOffset(0); } - + /** Creates a parent navigator a specified number of steps back from the top of the stack. */ function createParentNavigatorFromStackOffset(stackOffset: number): ParentNavigator { /** Gets the node two steps back from the current stack offset. */ function getGrandparent() { return peekNode(stackOffset + 2); } - + /** Gets the node one step back from the current stack offset. */ function getParent() { return peekNode(stackOffset + 1); } - + /** Gets the node at the current stack offset. */ function getNode() { return peekNode(stackOffset); } - + /** Gets the SyntaxKind of the node at the current stack offset. */ function getKind() { let node = getNode(); - return node ? node.kind : undefined; + return node ? node.kind : undefined; } - + /** Navigates to the node one step back from the current stack offset. */ function moveToParent() { if (getParent()) { stackOffset++; return true; } - + return false; } - + /** Navigates to the node at the bottom of the stack. */ function moveToRoot() { if (stackSize > 0) { stackOffset = stackSize; return true; } - + return false; } - + /** Creates a new ParentNavigator from the current stack offset. */ function createParentNavigator() { return createParentNavigatorFromStackOffset(stackOffset); } - + return { getGrandparent, getParent, @@ -1081,7 +1103,7 @@ namespace ts { createParentNavigator, }; } - + return { getGrandparent, getParent, @@ -1095,7 +1117,7 @@ namespace ts { createParentNavigator, }; } - + export const enum AssertionLevel { None = 0, Normal = 1, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c535b565171..8b4fe5157a8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,5 +1,5 @@ /// -/// +/// /// /* @internal */ @@ -14,7 +14,7 @@ namespace ts { CountMask = 0x0FFFFFFF, // Temp variable counter _i = 0x10000000, // Use/preference flag for '_i' } - + const enum StackBehavior { Unspecified, // No node stack behavior has been specified or should be necessary NodeIsOnTopOfStack, // The specified node is on the top of the node stack @@ -76,10 +76,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let newLine = host.getNewLine(); let jsxDesugaring = host.getCompilerOptions().jsx !== JsxEmit.Preserve; let shouldEmitJsx = (s: SourceFile) => (s.languageVariant === LanguageVariant.JSX && !jsxDesugaring); - let transformationChain = transform.getTransformationChain(compilerOptions); + let transformationChain = getTransformationChain(compilerOptions); + let sourceFiles: SourceFile[]; if (targetSourceFile === undefined) { - forEach(host.getSourceFiles(), sourceFile => { + sourceFiles = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain); + forEach(sourceFiles, sourceFile => { if (shouldEmitToOwnFile(sourceFile, compilerOptions)) { let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); emitFile(jsFilePath, sourceFile); @@ -94,9 +96,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service) if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) { let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js"); + [targetSourceFile] = transformFilesIfNeeded(resolver, host, [targetSourceFile], transformationChain); emitFile(jsFilePath, targetSourceFile); } else if (!isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) { + sourceFiles = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain); emitFile(compilerOptions.outFile || compilerOptions.out); } } @@ -111,7 +115,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi }; function isNodeDescendentOf(node: Node, ancestor: Node): boolean { - // node stack behavior: parent pointers are acceptable here as they refer to the original + // node stack behavior: parent pointers are acceptable here as they refer to the original // source tree while (node) { if (node === ancestor) return true; @@ -121,7 +125,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } function isUniqueLocalName(name: string, container: Node): boolean { - // node stack behavior: parent pointers are acceptable here as they refer to the original + // node stack behavior: parent pointers are acceptable here as they refer to the original // source tree for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) { if (node.locals && hasProperty(node.locals, name)) { @@ -150,8 +154,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let generatedNameSet: Map = {}; let nodeToGeneratedName: string[] = []; let computedPropertyNamesToGeneratedNames: string[]; - - // `nodeStack` is a stack consisting of each node in a branch of the + + // `nodeStack` is a stack consisting of each node in a branch of the // tree as we descend into the branch. It is used to derive the parent // node of any node without needing parent pointers, to help with // the emit of synthesized nodes that do not maintain parent pointers. @@ -218,13 +222,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitSourceFile(root); } else { - forEach(host.getSourceFiles(), sourceFile => { + forEach(sourceFiles, sourceFile => { if (!isExternalModuleOrDeclarationFile(sourceFile)) { emitSourceFile(sourceFile); } }); } - + writeLine(); writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM); return; @@ -237,13 +241,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi popNode = nodeStack.popNode; emit(sourceFile); } - + function findAncestorNode(match: (node: Node) => node is T): T; function findAncestorNode(match: (node: Node) => boolean): Node; function findAncestorNode(match: (node: Node) => boolean) { return nodeStack.findAncestorNode(match); } - + function isUniqueName(name: string): boolean { return !resolver.hasGlobalName(name) && !hasProperty(currentSourceFile.identifiers, name) && @@ -303,7 +307,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { verifyStackBehavior(StackBehavior.Unspecified); - + let expr = getExternalModuleName(node); let baseName = expr.kind === SyntaxKind.StringLiteral ? escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; @@ -312,19 +316,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function generateNameForExportDefault() { verifyStackBehavior(StackBehavior.Unspecified); - + return makeUniqueName("default"); } function generateNameForClassExpression() { verifyStackBehavior(StackBehavior.Unspecified); - + return makeUniqueName("class"); } function generateNameForNode(node: Node) { verifyStackBehavior(StackBehavior.Unspecified); - + switch (node.kind) { case SyntaxKind.Identifier: return makeUniqueName((node).text); @@ -347,7 +351,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getGeneratedNameForNode(node: Node) { verifyStackBehavior(StackBehavior.Unspecified); - + let id = getNodeId(node); return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node))); } @@ -738,11 +742,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } - + function emitNodeWithCommentsAndWithSourcemap(node: Node) { emitNodeConsideringCommentsOption(node, emitNodeWithSourceMapAndWithoutStackBehavior); } - + writeEmittedFiles = writeJavaScriptAndSourceMapFile; emit = emitNodeWithCommentsAndWithSourcemap; emitStart = recordEmitNodeStartSpan; @@ -778,7 +782,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitTempDeclarations(newLine: boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + if (tempVariables) { if (newLine) { writeLine(); @@ -794,7 +798,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) { verifyStackBehavior(StackBehavior.Unspecified); - + let tokenString = tokenToString(tokenKind); if (emitFn) { emitFn(); @@ -807,7 +811,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitOptional(prefix: string, node: Node) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (node) { write(prefix); emit(node); @@ -816,7 +820,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitParenthesizedIf(node: Node, parenthesized: boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (parenthesized) { write("("); } @@ -869,8 +873,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } decreaseIndent(); - - + + if (!synthesizedNodeStartsOnNewLine(lastNode) && (parentIsSynthesized || nodeEndPositionsAreOnSameLine(parent, lastNode))) { if (spacesBetweenBraces) { write(" "); @@ -883,7 +887,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitList(nodes: TNode[], start: number, count: number, multiLine: boolean, trailingComma: boolean, leadingComma?: boolean, noTrailingNewLine?: boolean, emitNode?: (node: TNode) => void): number { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + if (!emitNode) { emitNode = emit; } @@ -922,7 +926,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCommaList(nodes: Node[]) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + if (nodes) { emitList(nodes, 0, nodes.length, /*multiline*/ false, /*trailingComma*/ false); } @@ -930,13 +934,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitLines(nodes: Node[]) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + emitLinesStartingAt(nodes, /*startIndex*/ 0); } function emitLinesStartingAt(nodes: Node[], startIndex: number): void { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + for (let i = startIndex; i < nodes.length; i++) { writeLine(); emit(nodes[i]); @@ -945,7 +949,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isBinaryOrOctalIntegerLiteral(node: LiteralExpression, text: string): boolean { verifyStackBehavior(StackBehavior.Unspecified); - + if (node.kind === SyntaxKind.NumericLiteral && text.length > 1) { switch (text.charCodeAt(1)) { case CharacterCodes.b: @@ -961,7 +965,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitLiteral(node: LiteralExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let text = getLiteralText(node); if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { @@ -978,7 +982,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getLiteralText(node: LiteralExpression) { verifyStackBehavior(StackBehavior.Unspecified); - + // Any template literal or string literal with an extended escape // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { @@ -1017,7 +1021,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownlevelRawTemplateLiteral(node: LiteralExpression) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + // Find original source text, since we need to emit the raw strings of the tagged template. // The raw strings contain the (escaped) strings of what the user wrote. // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". @@ -1041,7 +1045,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownlevelTaggedTemplateArray(node: TaggedTemplateExpression, literalEmitter: (literal: LiteralExpression) => void) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("["); let template = node.template; if (template.kind === SyntaxKind.NoSubstitutionTemplateLiteral) { @@ -1060,7 +1064,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownlevelTaggedTemplate(node: TaggedTemplateExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let tempVariable = createAndRecordTempVariable(TempFlags.Auto); write("("); emit(tempVariable); @@ -1083,16 +1087,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } write("))"); } - + function emitTemplateSpansInTemplateExpressionForDownlevelTaggedTemplate(node: TemplateExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); forEach(node.templateSpans, emitTemplateSpanForDownlevelTaggedTemplateWithPushStackBehavior); } - + function emitTemplateSpanForDownlevelTaggedTemplateWithPushStackBehavior(node: TemplateSpan) { visitNodeWithPushStackBehavior(node, emitTemplateSpanForDownlevelTaggedTemplate); } - + function emitTemplateSpanForDownlevelTaggedTemplate(node: TemplateSpan) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); write(", "); @@ -1100,26 +1104,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi && (node.expression).operatorToken.kind === SyntaxKind.CommaToken; emitParenthesizedIf(node.expression, needsParens); } - + function emitTemplateExpression(node: TemplateExpression): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // In ES6 mode and above, we can simply emit each portion of a template in order, but in // ES3 & ES5 we must convert the template expression into a series of string concatenations. if (languageVersion >= ScriptTarget.ES6) { forEachChild(node, emit); return; } - + emitTemplateExpressionBelowES6(node); } - + function emitTemplateExpressionBelowES6(node: TemplateExpression): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); let nav = nodeStack.createParentNavigator(); nav.moveToParent(); - + let emitOuterParens = isExpression(nav) && templateNeedsParens(node); if (emitOuterParens) { write("("); @@ -1139,7 +1143,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // case. write(" + "); } - + visitNodeWithPushStackBehavior(templateSpan, emitTemplateSpanBelowES6); } @@ -1147,10 +1151,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(")"); } } - + function shouldEmitTemplateHead(node: TemplateExpression) { verifyStackBehavior(StackBehavior.Unspecified, node); - + // If this expression has an empty head literal and the first template span has a non-empty // literal, then emitting the empty head literal is not necessary. // `${ foo } and ${ bar }` @@ -1174,7 +1178,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function templateNeedsParens(template: TemplateExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, template); - + let parentNode = nodeStack.getParent(); switch (parentNode.kind) { case SyntaxKind.CallExpression: @@ -1187,17 +1191,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return comparePrecedenceToBinaryPlus(parentNode) !== Comparison.LessThan; } } - + function emitTemplateSpan(span: TemplateSpan) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, span); - + emit(span.expression); emit(span.literal); } function emitTemplateSpanBelowES6(node: TemplateSpan) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // Check if the expression has operands and binds its operands less closely than binary '+'. // If it does, we need to wrap the expression in parentheses. Otherwise, something like // `abc${ 1 << 2 }` @@ -1209,7 +1213,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // "abc" + (1 << 2) + "" let needsParens = node.expression.kind !== SyntaxKind.ParenthesizedExpression && comparePrecedenceToBinaryPlus(node.expression) !== Comparison.GreaterThan; - + emitParenthesizedIf(node.expression, needsParens); // Only emit if the literal is non-empty. @@ -1221,15 +1225,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi visitNodeWithPushStackBehavior(node.literal, emitLiteral); } } - + function jsxEmitReact(node: JsxElement|JsxSelfClosingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + /// Emit a tag name, which is either '"div"' for lower-cased names, or /// 'Div' for upper-cased or dotted names function emitTagName(name: Identifier|QualifiedName) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, name); - + if (name.kind === SyntaxKind.Identifier && isIntrinsicJsxName((name).text)) { write("\""); emit(name); @@ -1245,7 +1249,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /// about keywords, just non-identifier characters function emitAttributeName(name: Identifier) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, name); - + if (/[A-Za-z_]+[\w*]/.test(name.text)) { write("\""); emit(name); @@ -1259,7 +1263,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /// Emit an name/value pair for an attribute (e.g. "x: 3") function emitJsxAttribute(node: JsxAttribute) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitAttributeName(node.name); write(": "); if (node.initializer) { @@ -1269,13 +1273,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("true"); } } - + function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); emit(node.expression); } - function emitNonEmptyJsxText(node: JsxText) { + function emitNonEmptyJsxText(node: JsxText) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); let text = getTextToEmit(node); if (text !== undefined) { @@ -1284,10 +1288,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("\""); } } - + function emitJsxElement(openingNode: JsxOpeningLikeElement, children?: JsxChild[]) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, openingNode); - + let syntheticReactRef = createNode(SyntaxKind.Identifier); syntheticReactRef.text = 'React'; syntheticReactRef.parent = openingNode; @@ -1355,7 +1359,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (i > 0) { write(", "); } - + visitNodeWithPushStackBehavior(attrs[i], emitJsxAttribute); } write("}"); @@ -1385,7 +1389,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(")"); // closes "React.createElement(" emitTrailingComments(openingNode); } - + if (node.kind === SyntaxKind.JsxElement) { pushNode((node).openingElement); emitJsxElement((node).openingElement, (node).children); @@ -1396,13 +1400,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitJsxElement(node); } } - + function jsxEmitPreserve(node: JsxElement|JsxSelfClosingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + function emitJsxAttribute(node: JsxAttribute) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emit(node.name); if (node.initializer) { write("="); @@ -1412,7 +1416,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("{..."); emit(node.expression); write("}"); @@ -1420,12 +1424,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAttributes(attribs: NodeArray) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + for (let i = 0, n = attribs.length; i < n; i++) { if (i > 0) { write(" "); } - + pushNode(attribs[i]); if (attribs[i].kind === SyntaxKind.JsxSpreadAttribute) { emitJsxSpreadAttribute(attribs[i]); @@ -1440,7 +1444,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxOpeningOrSelfClosingElement(node: JsxOpeningElement|JsxSelfClosingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("<"); emit(node.tagName); if (node.attributes.length > 0 || (node.kind === SyntaxKind.JsxSelfClosingElement)) { @@ -1459,7 +1463,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxClosingElement(node: JsxClosingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(""); @@ -1467,7 +1471,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxElement(node: JsxElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + pushNode(node.openingElement); emitJsxOpeningOrSelfClosingElement(node.openingElement); popNode(); @@ -1495,7 +1499,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // For example, this is utilized when feeding in a result to Object.defineProperty. function emitExpressionForPropertyName(node: Declaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let name = node.name; Debug.assert(name.kind !== SyntaxKind.BindingElement); @@ -1522,10 +1526,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("\""); } } - + function emitExpressionForComputedPropertyName(name: ComputedPropertyName) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, name); - + // if this is a decorated computed property, we will need to capture the result // of the property expression so that we can apply decorators later. This is to ensure // we don't introduce unintended side effects: @@ -1562,7 +1566,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isExpressionIdentifier(node: Node): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let parentNode = nodeStack.getParent(); switch (parentNode.kind) { case SyntaxKind.ArrayLiteralExpression: @@ -1678,7 +1682,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isNameOfNestedRedeclaration(node: Identifier) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6) { let parentNode = nodeStack.getParent(); let originalNode = getOriginalNode(parentNode); @@ -1695,7 +1699,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitIdentifier(node: Identifier) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (nodeIsSynthesized(node) || !node.parent) { write(node.text); } @@ -1715,7 +1719,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitThis(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalThis) { write("_this"); } @@ -1726,7 +1730,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSuper(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion >= ScriptTarget.ES6) { write("super"); } @@ -1743,7 +1747,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitObjectBindingPattern(node: BindingPattern) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("{ "); let elements = node.elements; emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); @@ -1752,7 +1756,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitArrayBindingPattern(node: BindingPattern) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("["); let elements = node.elements; emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); @@ -1761,7 +1765,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBindingElement(node: BindingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.propertyName) { emit(node.propertyName); write(": "); @@ -1780,14 +1784,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSpreadElementExpression(node: SpreadElementExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("..."); emit((node).expression); } function emitYieldExpression(node: YieldExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(tokenToString(SyntaxKind.YieldKeyword)); if (node.asteriskToken) { write("*"); @@ -1800,7 +1804,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAwaitExpression(node: AwaitExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let needsParenthesis = needsParenthesisForAwaitExpressionAsYield(node); if (needsParenthesis) { write("("); @@ -1815,7 +1819,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function needsParenthesisForAwaitExpressionAsYield(node: AwaitExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let parentNode = nodeStack.getParent(); if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { return true; @@ -1829,7 +1833,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function needsParenthesisForPropertyAccessOrInvocation(node: Expression) { verifyStackBehavior(StackBehavior.Unspecified, node); - + switch (node.kind) { case SyntaxKind.Identifier: case SyntaxKind.ArrayLiteralExpression: @@ -1846,7 +1850,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitListWithSpread(elements: Expression[], needsUniqueCopy: boolean, multiLine: boolean, trailingComma: boolean, useConcat: boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + let pos = 0; let group = 0; let length = elements.length; @@ -1894,13 +1898,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isSpreadElementExpression(node: Node) { verifyStackBehavior(StackBehavior.Unspecified, node); - + return node.kind === SyntaxKind.SpreadElementExpression; } function emitArrayLiteral(node: ArrayLiteralExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let elements = node.elements; if (elements.length === 0) { write("[]"); @@ -1918,7 +1922,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitObjectLiteralBody(node: ObjectLiteralExpression, numElements: number): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (numElements === 0) { write("{}"); return; @@ -1960,7 +1964,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownlevelObjectLiteralWithComputedProperties(node: ObjectLiteralExpression, firstComputedPropertyIndex: number) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let multiLine = (node.flags & NodeFlags.MultiLine) !== 0; let properties = node.properties; @@ -2091,7 +2095,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitObjectLiteral(node: ObjectLiteralExpression): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let properties = node.properties; if (languageVersion < ScriptTarget.ES6) { @@ -2121,7 +2125,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitComputedPropertyName(node: ComputedPropertyName) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("["); emitExpressionForComputedPropertyName(node); write("]"); @@ -2129,7 +2133,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitMethod(node: MethodDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion >= ScriptTarget.ES6 && node.asteriskToken) { write("*"); } @@ -2143,7 +2147,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyAssignment(node: PropertyDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emit(node.name); write(": "); // This is to ensure that we emit comment in the following case: @@ -2160,14 +2164,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // Return true if identifier resolves to an exported member of a namespace function isNamespaceExportReference(node: Identifier) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + let container = resolver.getReferencedExportContainer(node); return container && container.kind !== SyntaxKind.SourceFile; } function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // The name property of a short-hand property assignment is considered an expression position, so here // we manually emit the identifier to avoid rewriting. writeTextOfNode(currentSourceFile, node.name); @@ -2189,7 +2193,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let constantValue = tryGetConstEnumValue(node); if (constantValue !== undefined) { write(constantValue.toString()); @@ -2201,13 +2205,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } return false; } - + function tryGetConstEnumValue(node: Node): number { if (compilerOptions.isolatedModules) { return undefined; } - - return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression + + return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression ? resolver.getConstantValue(node) : undefined } @@ -2217,7 +2221,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // emitted instead. function indentIfOnDifferentLines(parent: Node, node1: Node, node2: Node, valueToWriteWhenNotIndenting?: string): boolean { verifyStackBehavior(StackBehavior.Unspecified); - + let realNodesAreOnDifferentLines = !nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2); // Always use a newline for synthesized code if the synthesizer desires it. @@ -2238,7 +2242,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyAccess(node: PropertyAccessExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (tryEmitConstantValue(node)) { return; } @@ -2277,7 +2281,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitQualifiedName(node: QualifiedName) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emit(node.left); write("."); emit(node.right); @@ -2285,7 +2289,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean) { verifyStackBehavior(StackBehavior.Unspecified, node); - + if (node.left.kind === SyntaxKind.Identifier) { emitEntityNameAsExpression(node.left, useFallback); } @@ -2308,7 +2312,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) { verifyStackBehavior(StackBehavior.Unspecified, node); - + switch (node.kind) { case SyntaxKind.Identifier: if (useFallback) { @@ -2328,7 +2332,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitIndexedAccess(node: ElementAccessExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (tryEmitConstantValue(node)) { return; } @@ -2340,13 +2344,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function hasSpreadElement(elements: Expression[]) { verifyStackBehavior(StackBehavior.Unspecified); - + return forEach(elements, e => e.kind === SyntaxKind.SpreadElementExpression); } function skipParentheses(node: Expression): Expression { verifyStackBehavior(StackBehavior.Unspecified, node); - + while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { node = (node).expression; } @@ -2355,7 +2359,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCallTarget(node: Expression): Expression { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword) { emit(node); return node; @@ -2372,7 +2376,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCallWithSpread(node: CallExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let target: Expression; let expr = skipParentheses(node.expression); if (expr.kind === SyntaxKind.PropertyAccessExpression) { @@ -2423,7 +2427,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCallExpression(node: CallExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6 && hasSpreadElement(node.arguments)) { emitCallWithSpread(node); return; @@ -2460,7 +2464,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitNewExpression(node: NewExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("new "); // Spread operator logic is supported in new expressions in ES5 using a combination @@ -2503,7 +2507,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitTaggedTemplateExpression(node: TaggedTemplateExpression): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion >= ScriptTarget.ES6) { emit(node.tag); write(" "); @@ -2516,7 +2520,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitParenExpression(node: ParenthesizedExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // 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. @@ -2561,7 +2565,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDeleteExpression(node: DeleteExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(tokenToString(SyntaxKind.DeleteKeyword)); write(" "); emit(node.expression); @@ -2569,7 +2573,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitVoidExpression(node: VoidExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(tokenToString(SyntaxKind.VoidKeyword)); write(" "); emit(node.expression); @@ -2577,7 +2581,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitTypeOfExpression(node: TypeOfExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(tokenToString(SyntaxKind.TypeOfKeyword)); write(" "); emit(node.expression); @@ -2585,11 +2589,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node: Node): boolean { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (!isCurrentFileSystemExternalModule() || node.kind !== SyntaxKind.Identifier || nodeIsSynthesized(node)) { return false; } - + const parentNode = nodeStack.getNode(); const isVariableDeclarationOrBindingElement = parentNode && (parentNode.kind === SyntaxKind.VariableDeclaration || parentNode.kind === SyntaxKind.BindingElement); @@ -2598,13 +2602,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi isVariableDeclarationOrBindingElement ? parentNode : resolver.getReferencedValueDeclaration(node); - + return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true); } function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + const exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); if (exportChanged) { @@ -2648,7 +2652,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + const exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); if (exportChanged) { // export function returns the value that was passes as the second argument @@ -2676,7 +2680,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldHoistDeclarationInSystemJsModule(node: Node): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ false); } @@ -2692,11 +2696,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi */ function isSourceFileLevelDeclarationInSystemJsModule(node: Node, isExported: boolean): boolean { verifyStackBehavior(StackBehavior.Unspecified); - + if (!node || languageVersion >= ScriptTarget.ES6 || !isCurrentFileSystemExternalModule()) { return false; } - + // If `node` is not on top of the stack, then we get the combined node flags by // walking parent references. This should be safe as we should have received this // node from the checker, so we will be looking at the original source file. @@ -2719,7 +2723,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBinaryExpression(node: BinaryExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6 && node.operatorToken.kind === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) { let parentNode = nodeStack.getParent(); @@ -2755,7 +2759,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitConditionalExpression(node: ConditionalExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emit(node.condition); let indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " "); write("?"); @@ -2784,7 +2788,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isSingleLineEmptyBlock(node: Node) { verifyStackBehavior(StackBehavior.Unspecified, node); - + if (node && node.kind === SyntaxKind.Block) { let block = node; return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block); @@ -2797,10 +2801,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } 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; } @@ -2808,7 +2812,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBlock(node: Block) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (isSingleLineEmptyBlock(node)) { emitToken(SyntaxKind.OpenBraceToken, node.pos); write(" "); @@ -2827,7 +2831,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitToken(SyntaxKind.OpenBraceToken, node.pos); increaseIndent(); - + let parentNode = nodeStack.getParent(); scopeEmitStart(parentNode); if (node.kind === SyntaxKind.ModuleBlock) { @@ -2846,7 +2850,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitEmbeddedStatement(node: Node) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.Block) { write(" "); emit(node); @@ -2861,14 +2865,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExpressionStatement(node: ExpressionStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitParenthesizedIf(node.expression, /*parenthesized*/ node.expression.kind === SyntaxKind.ArrowFunction); write(";"); } function emitIfStatement(node: IfStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let endPos = emitToken(SyntaxKind.IfKeyword, node.pos); write(" "); endPos = emitToken(SyntaxKind.OpenParenToken, endPos); @@ -2890,7 +2894,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDoStatement(node: DoStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("do"); emitEmbeddedStatement(node.statement); if (node.statement.kind === SyntaxKind.Block) { @@ -2906,7 +2910,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitWhileStatement(node: WhileStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("while ("); emit(node.expression); write(")"); @@ -2920,7 +2924,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi */ function tryEmitStartOfVariableDeclarationList(decl: VariableDeclarationList, startPos?: number): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, decl); - + if (shouldHoistVariable(decl, /*checkIfSourceFileLevelDecl*/ true)) { // variables in variable declaration list were already hoisted return false; @@ -2959,7 +2963,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitVariableDeclarationListSkippingUninitializedEntries(list: VariableDeclarationList): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, list); - + let started = false; for (let decl of list.declarations) { if (!decl.initializer) { @@ -2981,7 +2985,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitForStatement(node: ForStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let endPos = emitToken(SyntaxKind.ForKeyword, node.pos); write(" "); endPos = emitToken(SyntaxKind.OpenParenToken, endPos); @@ -3010,7 +3014,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitForInOrForOfStatement(node: ForInStatement | ForOfStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.ForOfStatement) { return emitDownLevelForOfStatement(node); } @@ -3044,7 +3048,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownLevelForOfStatement(node: ForOfStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // The following ES6 code: // // for (let v of expr) { } @@ -3195,7 +3199,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBreakOrContinueStatement(node: BreakOrContinueStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitToken(node.kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword, node.pos); emitOptional(" ", node.label); write(";"); @@ -3203,7 +3207,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitReturnStatement(node: ReturnStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitToken(SyntaxKind.ReturnKeyword, node.pos); emitOptional(" ", node.expression); write(";"); @@ -3211,7 +3215,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitWithStatement(node: WithStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("with ("); emit(node.expression); write(")"); @@ -3220,7 +3224,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSwitchStatement(node: SwitchStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let endPos = emitToken(SyntaxKind.SwitchKeyword, node.pos); write(" "); emitToken(SyntaxKind.OpenParenToken, endPos); @@ -3234,7 +3238,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCaseBlock(node: CaseBlock, startPos: number): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitToken(SyntaxKind.OpenBraceToken, startPos); increaseIndent(); emitLines(node.clauses); @@ -3260,7 +3264,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCaseOrDefaultClause(node: CaseOrDefaultClause) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.CaseClause) { write("case "); emit((node).expression); @@ -3283,7 +3287,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitThrowStatement(node: ThrowStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("throw "); emit(node.expression); write(";"); @@ -3291,7 +3295,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitTryStatement(node: TryStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write("try "); emit(node.tryBlock); emit(node.catchClause); @@ -3304,7 +3308,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCatchClause(node: CatchClause) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + writeLine(); let endPos = emitToken(SyntaxKind.CatchKeyword, node.pos); write(" "); @@ -3317,14 +3321,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDebuggerStatement(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitToken(SyntaxKind.DebuggerKeyword, node.pos); write(";"); } function emitLabelledStatement(node: LabeledStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emit(node.label); write(": "); emit(node.statement); @@ -3337,11 +3341,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } 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 = getOriginalNode(findAncestorNode(isModuleDeclarationOrGeneratedNamespace)); write(container ? getGeneratedNameForNode(container) : "exports"); @@ -3349,7 +3353,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitModuleMemberName(node: Declaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitStart(node.name); if (getCombinedNodeFlags(nodeStack) & NodeFlags.Export) { let container = getOriginalNode(findAncestorNode(isModuleDeclarationOrGeneratedNamespace)); @@ -3388,7 +3392,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportMemberAssignment(node: FunctionLikeDeclaration | ClassDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.flags & NodeFlags.Export) { writeLine(); emitStart(node); @@ -3435,14 +3439,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (compilerOptions.module === ModuleKind.System) { return; } - + if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { for (let specifier of exportSpecifiers[name.text]) { writeLine(); emitStart(specifier.name); emitContainingModuleName(); write("."); - pushNode(specifier); + pushNode(specifier); emitNodeWithCommentsAndWithoutSourcemap(specifier.name); popNode(); emitEnd(specifier.name); @@ -3452,7 +3456,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } - + function emitExportSpecifierInSystemModule(specifier: ExportSpecifier): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, specifier); Debug.assert(compilerOptions.module === ModuleKind.System); @@ -3460,7 +3464,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (!resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name) && !resolver.isValueAliasDeclaration(specifier) ) { return; } - + writeLine(); emitStart(specifier.name); write(`${exportFunctionForFile}("`); @@ -3474,7 +3478,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, root); - + let emitCount = 0; // An exported declaration is actually emitted as an assignment (to a property on the module object), so @@ -3501,7 +3505,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAssignment(name: Identifier, value: Expression, isTempVariable?: boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, name); - + if (emitCount++) { write(", "); } @@ -3527,7 +3531,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(" = "); emit(value); - + if (exportChanged) { write(")"); } @@ -3544,7 +3548,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi */ function ensureIdentifier(expr: Expression, reuseIdentifierExpressions: boolean): Expression { verifyStackBehavior(StackBehavior.Unspecified); - + if (expr.kind === SyntaxKind.Identifier && reuseIdentifierExpressions) { return expr; } @@ -3559,14 +3563,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, target); - + let properties = target.properties; if (properties.length !== 1) { // For anything but a single element destructuring we need to generate a temporary // to ensure value is evaluated exactly once. value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true); } - + pushNode(target); for (let p of properties) { if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) { @@ -3582,14 +3586,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, target); - + let elements = target.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(value, /*reuseIdentifierExpressions*/ true); } - + pushNode(target); for (let i = 0; i < elements.length; i++) { let e = elements[i]; @@ -3609,7 +3613,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDestructuringAssignment(target: Expression, value: Expression) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, target); - + if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { value = createDefaultValueCheck(value, (target).right, ensureIdentifier); target = (target).left; @@ -3627,7 +3631,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAssignmentExpression(node: BinaryExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let target = node.left; let value = node.right; @@ -3654,7 +3658,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBindingElement(target: BindingElement | VariableDeclaration, value: Expression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, target); - + if (target.initializer) { // Combine value and initializer value = value ? createDefaultValueCheck(value, target.initializer, ensureIdentifier) : target.initializer; @@ -3663,7 +3667,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // Use 'void 0' in absence of value and initializer value = createVoidZeroExpression(); } - + if (isBindingPattern(target.name)) { const pattern = target.name; const elements = pattern.elements; @@ -3706,7 +3710,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitVariableDeclaration(node: VariableDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (isBindingPattern(node.name)) { if (languageVersion < ScriptTarget.ES6) { emitDestructuring(node, /*isAssignmentExpressionStatement*/ false); @@ -3760,7 +3764,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportVariableAssignments(node: VariableDeclaration | BindingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.OmittedExpression) { return; } @@ -3772,7 +3776,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi forEach((name).elements, emitExportVariableAssignmentsOfChild); } } - + function emitExportVariableAssignmentsOfChild(node: VariableDeclaration | BindingElement) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); pushNode(node); @@ -3782,7 +3786,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getCombinedFlagsForIdentifier(name: Identifier): NodeFlags { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, name); - + let parentNode = nodeStack.getNode(); if (!parentNode || (parentNode.kind !== SyntaxKind.VariableDeclaration && parentNode.kind !== SyntaxKind.BindingElement)) { return 0; @@ -3793,7 +3797,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isES6ExportedDeclaration(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return !!(node.flags & NodeFlags.Export) && languageVersion >= ScriptTarget.ES6 && nodeStack.getParent().kind === SyntaxKind.SourceFile; @@ -3801,10 +3805,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitVariableStatement(node: VariableStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let declarationList = node.declarationList; let startIsEmitted = false; - + if (node.flags & NodeFlags.Export) { if (isES6ExportedDeclaration(node)) { // Exported ES6 module member @@ -3834,7 +3838,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(";"); } } - + if (languageVersion < ScriptTarget.ES6 && nodeStack.getParent() === currentSourceFile) { pushNode(declarationList); forEach(declarationList.declarations, emitExportVariableAssignmentsOfChild); @@ -3844,7 +3848,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitLeadingAndTrailingCommentsForVariableStatement(node: VariableStatement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // If we're not exporting the variables, there's nothing special here. // Always emit comments for these nodes. if (!(node.flags & NodeFlags.Export)) { @@ -3868,7 +3872,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitParameter(node: ParameterDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6) { if (isBindingPattern(node.name)) { let name = createTempVariable(TempFlags.Auto); @@ -3893,7 +3897,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDefaultValueAssignments(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6) { let tempIndex = 0; forEach(node.parameters, parameter => { @@ -3949,7 +3953,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitRestParameter(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6 && hasRestParameter(node)) { let restIndex = node.parameters.length - 1; let restParam = node.parameters[restIndex]; @@ -3958,7 +3962,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (isBindingPattern(restParam.name)) { return; } - + pushNode(restParam); let tempName = createTempVariable(TempFlags._i).text; writeLine(); @@ -3998,7 +4002,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAccessor(node: AccessorDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); emit(node.name); emitSignatureAndBody(node); @@ -4006,13 +4010,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitAsArrowFunction(node: FunctionLikeDeclaration): boolean { verifyStackBehavior(StackBehavior.Unspecified, node); - + return node.kind === SyntaxKind.ArrowFunction && languageVersion >= ScriptTarget.ES6; } - + function emitDeclarationName(node: Declaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.name) { emitNodeWithCommentsAndWithoutSourcemap(node.name); } @@ -4023,7 +4027,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitFunctionName(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.FunctionExpression) { // Emit name if one is present return !!node.name; @@ -4036,7 +4040,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitFunctionDeclaration(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (nodeIsMissing(node.body)) { return emitCommentsOnNotEmittedNode(node); } @@ -4097,11 +4101,11 @@ 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); @@ -4112,7 +4116,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSignatureParameters(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + increaseIndent(); write("("); if (node) { @@ -4126,7 +4130,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSignatureParametersForArrow(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // Check whether the parameter list needs parentheses and preserve no-parenthesis if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) { emit(node.parameters[0]); @@ -4138,7 +4142,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAsyncFunctionBodyForES6(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let promiseConstructor = getEntityNameFromTypeNode(node.type); let isArrowFunction = node.kind === SyntaxKind.ArrowFunction; let hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0; @@ -4264,7 +4268,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitFunctionBody(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (!node.body) { // There can be no body when there are parse errors. Just emit an empty block // in that case. @@ -4282,7 +4286,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSignatureAndBody(node: FunctionLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let saveTempFlags = tempFlags; let saveTempVariables = tempVariables; let saveTempParameters = tempParameters; @@ -4319,7 +4323,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // Returns true if any preamble code was emitted. function emitFunctionBodyPreamble(node: FunctionLikeDeclaration): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitCaptureThisForNodeIfNecessary(node); emitDefaultValueAssignments(node); emitRestParameter(node); @@ -4327,7 +4331,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExpressionFunctionBody(node: FunctionLikeDeclaration, body: Expression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6 || node.flags & NodeFlags.Async) { emitDownLevelExpressionFunctionBody(node, body); return; @@ -4350,7 +4354,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDownLevelExpressionFunctionBody(node: FunctionLikeDeclaration, body: Expression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(" {"); scopeEmitStart(node); @@ -4400,7 +4404,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBlockFunctionBody(node: FunctionLikeDeclaration, body: Block) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + write(" {"); scopeEmitStart(node); @@ -4417,8 +4421,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi pushNode(body); let preambleEmitted = writer.getTextPos() !== initialTextPos; - if (!preambleEmitted && !nodeIsSynthesized(body) - && nodeEndIsOnSameLineAsNodeStart(body, body) + if (!preambleEmitted && !nodeIsSynthesized(body) + && nodeEndIsOnSameLineAsNodeStart(body, body) && !isBlockWithSynthesizedStatementsOnNewLine(body) && (!nodeIsSynthesized(body) || isSingleLineSynthesizedBlock(body))) { for (let statement of body.statements) { @@ -4446,7 +4450,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, ctor); - + if (ctor.body) { let statement = (ctor.body).statements[0]; if (statement && statement.kind === SyntaxKind.ExpressionStatement) { @@ -4463,7 +4467,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitParameterPropertyAssignments(node: ConstructorDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + forEach(node.parameters, param => { if (param.flags & NodeFlags.AccessibilityModifier) { writeLine(); @@ -4482,7 +4486,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitMemberAccessForPropertyName(member: Declaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, member); - + let memberName = member.name; // This does not emit source map because it is emitted by caller as caller // is aware how the property name changes to the property access @@ -4507,7 +4511,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getInitializedProperties(node: ClassLikeDeclaration, isStatic: boolean) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let properties: PropertyDeclaration[] = []; for (let member of node.members) { if (member.kind === SyntaxKind.PropertyDeclaration && isStatic === ((member.flags & NodeFlags.Static) !== 0) && (member).initializer) { @@ -4520,7 +4524,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyDeclarations(node: ClassLikeDeclaration, properties: PropertyDeclaration[]) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + for (let property of properties) { emitPropertyDeclaration(node, property); } @@ -4528,7 +4532,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + writeLine(); pushNode(property); emitLeadingComments(property); @@ -4562,7 +4566,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitMemberFunctionsForES5AndLower(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + forEach(node.members, member => { if (member.kind === SyntaxKind.SemicolonClassElement) { writeLine(); @@ -4571,7 +4575,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi else if (member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) { if (!(member).body) { pushNode(member); - return emitCommentsOnNotEmittedNode(member); + emitCommentsOnNotEmittedNode(member); popNode(); return; } @@ -4652,7 +4656,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitMemberFunctionsForES6AndHigher(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + for (let member of node.members) { pushNode(member); if ((member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && !(member).body) { @@ -4695,7 +4699,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitConstructor(node: ClassLikeDeclaration, baseTypeElement: ExpressionWithTypeArguments) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let saveTempFlags = tempFlags; let saveTempVariables = tempVariables; let saveTempParameters = tempParameters; @@ -4712,7 +4716,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitConstructorWorker(node: ClassLikeDeclaration, baseTypeElement: ExpressionWithTypeArguments) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // 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 @@ -4738,7 +4742,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (languageVersion >= ScriptTarget.ES6 && !ctor && !hasInstancePropertyWithInitializer) { return; } - + if (ctor) { pushNode(ctor); emitLeadingComments(ctor); @@ -4855,19 +4859,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitClassExpression(node: ClassExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return emitClassLikeDeclaration(node); } function emitClassDeclaration(node: ClassDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return emitClassLikeDeclaration(node); } function emitClassLikeDeclaration(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6) { emitClassLikeDeclarationBelowES6(node); } @@ -4878,7 +4882,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitClassLikeDeclarationForES6AndHigher(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let thisNodeIsDecorated = nodeIsDecorated(node); if (node.kind === SyntaxKind.ClassDeclaration) { if (thisNodeIsDecorated) { @@ -5035,7 +5039,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (!isClassExpression(node)) { writeLine(); } - + emitPropertyDeclarations(node, staticProperties); emitDecoratorsOfClass(node); } @@ -5063,7 +5067,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) { // source file level classes in system modules are hoisted so 'var's for them are already defined if (!shouldHoistDeclarationInSystemJsModule(node)) { @@ -5142,7 +5146,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitClassMemberPrefix(node: ClassLikeDeclaration, member: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitDeclarationName(node); if (!(member.flags & NodeFlags.Static)) { write(".prototype"); @@ -5151,7 +5155,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDecoratorsOfClass(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitDecoratorsOfMembers(node, /*staticFlag*/ 0); emitDecoratorsOfMembers(node, NodeFlags.Static); emitDecoratorsOfConstructor(node); @@ -5159,7 +5163,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let decorators = node.decorators; let constructor = getFirstConstructorWithBody(node); let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated); @@ -5199,13 +5203,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (constructor) { pushNode(constructor); } - + argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0); - + if (constructor) { popNode(); } - + emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0); decreaseIndent(); @@ -5219,7 +5223,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDecoratorsOfMembers(node: ClassLikeDeclaration, staticFlag: NodeFlags) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + for (let member of node.members) { // only emit members in the correct group if ((member.flags & NodeFlags.Static) !== staticFlag) { @@ -5227,8 +5231,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } // skip members that cannot be decorated (such as the constructor) - if (member.kind !== SyntaxKind.PropertyDeclaration - && ((member.kind !== SyntaxKind.GetAccessor + if (member.kind !== SyntaxKind.PropertyDeclaration + && ((member.kind !== SyntaxKind.GetAccessor && member.kind !== SyntaxKind.SetAccessor && member.kind !== SyntaxKind.MethodDeclaration) || !(member).body)) { @@ -5239,7 +5243,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (!nodeOrChildIsDecorated(member)) { continue; } - + // skip an accessor declaration if it is not the first accessor let decorators: NodeArray; let functionLikeMember: FunctionLikeDeclaration; @@ -5330,14 +5334,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi popNode(); }); popNode(); - - + + if (functionLikeMember) { pushNode(functionLikeMember); argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0); popNode(); } - + pushNode(member); emitSerializedTypeMetadata(member, argumentsWritten > 0); popNode(); @@ -5374,7 +5378,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, leadingComma: boolean): number { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let argumentsWritten = 0; if (node) { let parameterIndex = 0; @@ -5400,7 +5404,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitTypeMetadata(node: Declaration): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // 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. @@ -5417,7 +5421,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitReturnTypeMetadata(node: Declaration): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // 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. @@ -5430,7 +5434,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitParamTypesMetadata(node: Declaration): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // 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. @@ -5446,7 +5450,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */ function emitSerializedTypeOfNode(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // serialization of the type of a declaration uses the following rules: // // * The serialized type of a ClassDeclaration is "Function" @@ -5487,10 +5491,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("void 0"); } - + function emitSerializedTypeNode(node: TypeNode) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (node) { switch (node.kind) { @@ -5556,7 +5560,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ function emitSerializedTypeReferenceNode(node: TypeReferenceNode) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let location: Node = node.parent; while (isDeclaration(location) || isTypeNode(location)) { location = location.parent; @@ -5625,7 +5629,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */ function emitSerializedParameterTypesOfNode(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // serialization of parameter types uses the following rules: // // * If the declaration is a class, the parameters of the first constructor with a body are used. @@ -5649,7 +5653,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (i > 0) { write(", "); } - + let parameter = parameters[i]; if (parameter.dotDotDotToken) { let parameterType = parameters[i].type; @@ -5677,7 +5681,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes the return type of function. Used by the __metadata decorator for a method. */ function emitSerializedReturnTypeOfNode(node: Node): string | string[] { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node && isFunctionLike(node) && (node).type) { emitSerializedTypeNode((node).type); return; @@ -5689,7 +5693,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // This method emits the serialized type metadata for a decorator target. // The caller should have already tested whether the node has decorators. let argumentsWritten = 0; @@ -5732,13 +5736,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitInterfaceDeclaration(node: InterfaceDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitCommentsOnNotEmittedNode(node); } function shouldEmitEnumDeclaration(node: EnumDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let isConstEnum = isConst(node); return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; } @@ -5746,7 +5750,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. if (!shouldEmitEnumDeclaration(node)) { return; @@ -5812,7 +5816,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitEnumMember(node: EnumMember) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let enumParent = nodeStack.getParent(); emitStart(node); write(getGeneratedNameForNode(enumParent)); @@ -5830,7 +5834,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function writeEnumMemberDeclarationValue(member: EnumMember) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, member); - + let value = resolver.getConstantValue(member); if (value !== undefined) { write(value.toString()); @@ -5846,7 +5850,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration { verifyStackBehavior(StackBehavior.Unspecified); - + if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { let recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); return recursiveInnerModule || moduleDeclaration.body; @@ -5855,28 +5859,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function shouldEmitModuleDeclaration(node: ModuleDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); } function isModuleMergedWithES6Class(node: ModuleDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return languageVersion === ScriptTarget.ES6 && !!(resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass); } 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. let shouldEmit = shouldEmitModuleDeclaration(node); if (!shouldEmit) { return emitCommentsOnNotEmittedNode(node); } - + let hoistedInDeclarationScope = shouldHoistDeclarationInSystemJsModule(node); let emitVarForModule = !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node); @@ -5945,10 +5949,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitExportMemberAssignments(node.name); } } - + /* - * Some bundlers (SystemJS builder) sometimes want to rename dependencies. - * Here we check if alternative name was provided for a given moduleName and return it if possible. + * Some bundlers (SystemJS builder) sometimes want to rename dependencies. + * Here we check if alternative name was provided for a given moduleName and return it if possible. */ function tryRenameExternalModule(moduleName: LiteralExpression): string { if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) { @@ -5959,7 +5963,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitRequire(moduleName: Expression) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, moduleName); - + if (moduleName.kind === SyntaxKind.StringLiteral) { write("require("); let text = tryRenameExternalModule(moduleName); @@ -5982,7 +5986,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.kind === SyntaxKind.ImportEqualsDeclaration) { return node; } @@ -5994,22 +5998,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return node.kind === SyntaxKind.ImportDeclaration && (node).importClause && !!(node).importClause.name; } function emitExportImportAssignments(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { emitExportMemberAssignments((node).name); } forEachChild(node, emitExportImportAssignmentsOfChild); } - + function emitExportImportAssignmentsOfChild(node: Node) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + pushNode(node); emitExportImportAssignments(node); popNode(); @@ -6017,7 +6021,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitImportDeclaration(node: ImportDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (languageVersion < ScriptTarget.ES6) { return emitExternalImportDeclaration(node); } @@ -6029,17 +6033,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let shouldEmitNamedBindings = importClause.namedBindings && resolver.isReferencedAliasDeclaration(importClause.namedBindings, /* checkChildren */ true); if (shouldEmitDefaultBindings || shouldEmitNamedBindings) { write("import "); - + pushNode(importClause); emitStart(importClause); - + if (shouldEmitDefaultBindings) { emit(importClause.name); if (shouldEmitNamedBindings) { write(", "); } } - + if (shouldEmitNamedBindings) { let namedBindings = importClause.namedBindings; pushNode(namedBindings); @@ -6061,7 +6065,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitEnd(importClause); popNode(); - + write(" from "); emit(node.moduleSpecifier); write(";"); @@ -6076,7 +6080,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (contains(externalImports, node)) { let isExportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && (node.flags & NodeFlags.Export) !== 0; let namespaceDeclaration = getNamespaceDeclarationNode(node); @@ -6167,7 +6171,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (isExternalModuleImportEqualsDeclaration(node)) { emitExternalImportDeclaration(node); return; @@ -6224,7 +6228,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportDeclaration(node: ExportDeclaration) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + Debug.assert(compilerOptions.module !== ModuleKind.System); if (languageVersion < ScriptTarget.ES6) { @@ -6296,7 +6300,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportOrImportSpecifierList(specifiers: ImportOrExportSpecifier[], shouldEmit: (node: Node) => boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + Debug.assert(languageVersion >= ScriptTarget.ES6); let needsComma = false; @@ -6317,7 +6321,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportAssignment(node: ExportAssignment) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) { if (languageVersion >= ScriptTarget.ES6) { writeLine(); @@ -6357,7 +6361,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function collectExternalModuleInfo(sourceFile: SourceFile) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, sourceFile); - + externalImports = []; exportSpecifiers = {}; exportEquals = undefined; @@ -6412,7 +6416,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportStarHelper() { verifyStackBehavior(StackBehavior.Unspecified); - + if (hasExportStars) { writeLine(); write("function __export(m) {"); @@ -6424,7 +6428,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("}"); } } - + function getLocalNameForExternalImportWithPushStackBehavior(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); pushNode(node); @@ -6435,7 +6439,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); @@ -6450,10 +6454,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getExternalModuleNameText(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, importNode); - + let moduleName = getExternalModuleName(importNode); if (moduleName.kind === SyntaxKind.StringLiteral) { - return tryRenameExternalModule(moduleName) || getLiteralText(moduleName); + return tryRenameExternalModule(moduleName) || getLiteralText(moduleName); } return undefined; @@ -6461,7 +6465,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitVariableDeclarationsForImports(): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack); - + if (externalImports.length === 0) { return; } @@ -6496,7 +6500,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitLocalStorageForExportedNamesIfNecessary(exportedDeclarations: Declaration[]): string { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + // when resolving exports local exported entries/indirect exported entries in the module // should always win over entries with similar names that were added via star exports // to support this we store names of local/indirect exported entries in a set. @@ -6553,7 +6557,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (externalImport.kind !== SyntaxKind.ExportDeclaration) { continue; } - + let exportDecl = externalImport; if (!exportDecl.exportClause) { // export * from ... @@ -6568,7 +6572,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeExportedName(element.name || element.propertyName); popNode(); } - + popNode(); popNode(); } @@ -6581,7 +6585,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportStarFunction(localNames: string): string { verifyStackBehavior(StackBehavior.Unspecified); - + const exportStarFunction = makeUniqueName("exportStar"); writeLine(); @@ -6614,7 +6618,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function writeExportedName(node: Identifier | Declaration): void { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + // do not record default exports // they are local to module and never overwritten (explicitly skipped) by star export if (node.kind !== SyntaxKind.Identifier && node.flags & NodeFlags.Default) { @@ -6645,7 +6649,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function processTopLevelVariableAndFunctionDeclarations(statements: NodeArray): Declaration[] { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + // per ES6 spec: // 15.2.1.16.4 ModuleDeclarationInstantiation() Concrete Method // - var declarations are initialized to undefined - 14.a.ii @@ -6681,10 +6685,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } return exportedDeclarations; - + function visitChild(node: Node): void { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + pushNode(node); visit(node); popNode(); @@ -6692,7 +6696,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function visit(node: Node): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.flags & NodeFlags.Ambient) { return; } @@ -6705,7 +6709,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi hoistedFunctionDeclarations.push(node); return; } - + hoist: if (shouldHoistNode(node)) { let name = node.name; if (name && name.kind === SyntaxKind.Identifier) { @@ -6727,9 +6731,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi else { write(", "); } - + emitDeclarationName(node); - + let flags = getCombinedNodeFlags(nodeStack); if (flags & NodeFlags.Export) { if (!exportedDeclarations) { @@ -6749,32 +6753,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } - + function shouldHoistNode(node: Node): node is Declaration { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + switch (node.kind) { case SyntaxKind.ClassDeclaration: return true; - + case SyntaxKind.EnumDeclaration: return shouldEmitEnumDeclaration(node); - + case SyntaxKind.ModuleDeclaration: return shouldEmitModuleDeclaration(node); - + case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: return shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ false) && (node).name.kind === SyntaxKind.Identifier; } - + return isInternalModuleImportEqualsDeclaration(node) && resolver.isValueAliasDeclaration(node); } function shouldHoistVariable(node: VariableDeclaration | VariableDeclarationList | BindingElement, checkIfSourceFileLevelDecl: boolean): boolean { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (checkIfSourceFileLevelDecl && !shouldHoistDeclarationInSystemJsModule(node)) { return false; } @@ -6793,7 +6797,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSystemModuleBody(statements: NodeArray, dependencyGroups: DependencyGroup[], startIndex: number): void { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + // shape of the body in system modules: // function (exports) { // @@ -6849,9 +6853,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitSetters(exportStarFunction: string, dependencyGroups: DependencyGroup[]) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + write("setters:["); - + for (let i = 0; i < dependencyGroups.length; ++i) { if (i !== 0) { write(","); @@ -6859,17 +6863,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); increaseIndent(); - + let group = dependencyGroups[i]; - + // derive a unique name for parameter from the first named entry in the group let parameterName = makeUniqueName(forEach(group, getLocalNameForExternalImportWithPushStackBehavior) || ""); write(`function (${parameterName}) {`); increaseIndent(); - + for(let entry of group) { let importVariableName = getLocalNameForExternalImportWithPushStackBehavior(entry) || ""; - + switch (entry.kind) { case SyntaxKind.ImportDeclaration: if (!(entry).importClause) { @@ -6906,7 +6910,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(","); writeLine(); } - + let e = (entry).exportClause.elements[i]; pushNode(e); write(`"`); @@ -6945,7 +6949,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExecute(statements: NodeArray, startIndex: number) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + write("execute: function() {"); increaseIndent(); writeLine(); @@ -6982,18 +6986,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi default: writeLine(); emit(statement); - } + } } decreaseIndent(); writeLine(); write("}"); // execute } - + type DependencyGroup = Array; - + function emitSystemModule(node: SourceFile, statements: NodeArray, startIndex: number): void { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + collectExternalModuleInfo(node); // System modules has the following shape // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) @@ -7012,7 +7016,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(`"${node.moduleName}", `); } write("["); - + let groupIndices: Map = {}; let dependencyGroups: DependencyGroup[] = []; @@ -7035,10 +7039,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (i !== 0) { write(", "); } - + write(text); } - + write(`], function(${exportFunctionForFile}) {`); writeLine(); increaseIndent(); @@ -7052,7 +7056,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAMDDependencies(node: SourceFile, includeNonAmdDependencies: boolean) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // An AMD define function has the following shape: // define(id?, dependencies?, factory); // @@ -7119,7 +7123,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitAMDModule(node: SourceFile, statements: NodeArray, startIndex: number) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitEmitHelpers(node); collectExternalModuleInfo(node); @@ -7143,7 +7147,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitCommonJSModule(node: SourceFile, statements: NodeArray, startIndex: number) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitEmitHelpers(node); collectExternalModuleInfo(node); emitExportStarHelper(); @@ -7155,7 +7159,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitUMDModule(node: SourceFile, statements: NodeArray, startIndex: number) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitEmitHelpers(node); collectExternalModuleInfo(node); @@ -7183,7 +7187,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitES6Module(node: SourceFile, statements: NodeArray, startIndex: number) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + externalImports = undefined; exportSpecifiers = undefined; exportEquals = undefined; @@ -7198,7 +7202,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportEquals(emitAsReturn: boolean) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, exportEquals); - + if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) { pushNode(exportEquals); writeLine(); @@ -7213,7 +7217,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxElement(node: JsxElement | JsxSelfClosingElement) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + switch (compilerOptions.jsx) { case JsxEmit.React: jsxEmitReact(node); @@ -7228,7 +7232,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function trimReactWhitespaceAndApplyEntities(node: JsxText): string { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + let result: string = undefined; let text = getTextOfNode(node, /*includeTrivia*/ true); let firstNonWhitespace = 0; @@ -7276,7 +7280,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getTextToEmit(node: JsxText) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + switch (compilerOptions.jsx) { case JsxEmit.React: let text = trimReactWhitespaceAndApplyEntities(node); @@ -7294,7 +7298,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxText(node: JsxText) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + switch (compilerOptions.jsx) { case JsxEmit.React: write("\""); @@ -7311,7 +7315,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJsxExpression(node: JsxExpression) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + if (node.expression) { switch (compilerOptions.jsx) { case JsxEmit.Preserve: @@ -7327,9 +7331,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitDirectivePrologues(statements: Node[], startWithNewLine: boolean): number { + function emitDirectivePrologues(statements: Statement[], startWithNewLine: boolean): number { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack); - + for (let i = 0; i < statements.length; ++i) { if (isPrologueDirective(statements[i])) { if (startWithNewLine || i > 0) { @@ -7345,9 +7349,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return statements.length; } + function emitRaw(node: RawExpression | RawStatement) { + verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); + writeLines(node.text); + } + function writeLines(text: string): void { verifyStackBehavior(StackBehavior.Unspecified); - + let lines = text.split(/\r\n|\r|\n/g); for (let i = 0; i < lines.length; ++i) { let line = lines[i]; @@ -7397,12 +7406,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); emitShebang(); emitDetachedComments(node); - + // Process tree transformations let statements = node.statements; - if (compilerOptions.experimentalTransforms) { - statements = runTransformationChain(statements, transformationChain, compilerOptions, currentSourceFile, resolver, generatedNameSet, nodeToGeneratedName); - } // emit prologue directives prior to __extends let startIndex = emitDirectivePrologues(statements, /*startWithNewLine*/ false); @@ -7437,7 +7443,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi visitNodeWithPushStackBehavior(node.endOfFileToken, emitLeadingComments); } - + function visitNodeWithPushStackBehavior(node: T, visit: (node: T) => U): U; function visitNodeWithPushStackBehavior(node: T, pipe: (node: T, emitNode: (node: T) => U) => U, visit?: (node: T) => U): U; function visitNodeWithPushStackBehavior(node: T, pipe: (node: T, emitNode?: (node: T) => U) => U, visit?: (node: T) => U): U { @@ -7448,7 +7454,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi result = visit ? pipe(node, visit) : pipe(node); popNode(); } - + return result; } @@ -7459,9 +7465,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitNodeConsideringCommentsOption(node: Node, emitNodeConsideringSourcemapWithoutStackBehavior: (node: Node) => void): void { if (node) { verifyStackBehavior(StackBehavior.ParentIsOnTopOfStack, node); - + if (node.flags & NodeFlags.Ambient || isMissingDeclaration(node)) { - return emitCommentsOnNotEmittedNode(node); + return visitNodeWithPushStackBehavior(node, emitCommentsOnNotEmittedNode); } if (isSpecializedCommentHandling(node)) { @@ -7472,10 +7478,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi visitNodeWithPushStackBehavior(node, emitNodeWithCommentsAndWithoutStackBehavior, emitNodeConsideringSourcemapWithoutStackBehavior); } } - + function emitNodeWithCommentsAndWithoutStackBehavior(node: Node, emitNodeConsideringSourcemapWithoutStackBehavior: (node: Node) => void): void { verifyStackBehavior(StackBehavior.Unspecified, node); - + let emitComments = shouldEmitLeadingAndTrailingComments(node); if (emitComments) { emitLeadingComments(node); @@ -7487,13 +7493,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitTrailingComments(node); } } - + function emitNodeWithoutSourceMap(node: Node): void { if (node) { visitNodeWithPushStackBehavior(node, emitNodeWithoutSourceMapAndWithoutStackBehavior); } } - + function emitNodeWithoutSourceMapAndWithoutStackBehavior(node: Node): void { if (node) { emitJavaScriptWorker(node); @@ -7502,7 +7508,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function isSpecializedCommentHandling(node: Node): boolean { verifyStackBehavior(StackBehavior.Unspecified, node); - + switch (node.kind) { // All of these entities are emitted in a specialized fashion. As such, we allow // the specialized methods for each to handle the comments on the nodes. @@ -7532,7 +7538,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return shouldEmitEnumDeclaration(node); } - // If the node is emitted in specialized fashion, dont emit comments as this node will handle + // If the node is emitted in specialized fashion, dont emit comments as this node will handle // emitting comments when emitting itself Debug.assert(!isSpecializedCommentHandling(node)); @@ -7556,7 +7562,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJavaScriptWorker(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // Check if the node can be emitted regardless of the ScriptTarget switch (node.kind) { case SyntaxKind.Identifier: @@ -7724,18 +7730,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return emitExportAssignment(node); case SyntaxKind.SourceFile: return emitSourceFileNode(node); + case SyntaxKind.RawExpression: + case SyntaxKind.RawStatement: + return emitRaw(node); } } function hasDetachedComments(pos: number) { verifyStackBehavior(StackBehavior.Unspecified); - + return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos; } function getLeadingCommentsWithoutDetachedComments() { verifyStackBehavior(StackBehavior.Unspecified); - + // get the leading comments from detachedPos let leadingComments = getLeadingCommentRanges(currentSourceFile.text, lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); @@ -7775,7 +7784,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getLeadingCommentsToEmit(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments let parentNode = nodeStack.getParent(); if (parentNode) { @@ -7794,7 +7803,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function getTrailingCommentsToEmit(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments let parentNode = nodeStack.getParent(); if (parentNode && !nodeIsSynthesized(parentNode)) { @@ -7809,13 +7818,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi */ function emitCommentsOnNotEmittedNode(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + emitLeadingCommentsWorker(node, /*isEmittedNode:*/ false); } function emitLeadingComments(node: Node) { verifyStackBehavior(StackBehavior.NodeIsOnTopOfStack, node); - + return emitLeadingCommentsWorker(node, /*isEmittedNode:*/ true); } @@ -7824,7 +7833,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (compilerOptions.removeComments) { return; } - + let leadingComments: CommentRange[]; if (isEmittedNode) { leadingComments = getLeadingCommentsToEmit(node); @@ -7960,20 +7969,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } - + function emitShebang() { let shebang = getShebang(currentSourceFile.text); if (shebang) { write(shebang); } } - + function verifyStackBehavior(behavior: StackBehavior, node?: Node) { let currentNode = nodeStack.getNode(); switch (behavior) { case StackBehavior.Unspecified: return; - + case StackBehavior.NodeIsOnTopOfStack: if (node) { Debug.assert(currentNode === node, "Incorrect node stack behavior. Expected node to be on the top of the stack."); @@ -7982,7 +7991,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi Debug.assert(currentNode !== undefined, "Incorrect node stack behavior. Expected node to be on the top of the stack."); } return; - + case StackBehavior.ParentIsOnTopOfStack: Debug.assert(currentNode !== node, "Incorrect node stack behavior. Expected parent of node to be on the top of the stack."); return; @@ -7994,7 +8003,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitJavaScript(jsFilePath, sourceFile); if (compilerOptions.declaration) { - writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics); + writeDeclarationFile(jsFilePath, getOriginalNodeIf(sourceFile, isSourceFile), host, resolver, diagnostics); } } } diff --git a/src/compiler/factory.generated.ts b/src/compiler/factory.generated.ts index fc68815d5c7..be8e5e29d2d 100644 --- a/src/compiler/factory.generated.ts +++ b/src/compiler/factory.generated.ts @@ -1,3422 +1,3411 @@ -// -/// -namespace ts { - export function createNumericLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.NumericLiteral, location, flags); - node.text = text; - return node; - } - export function createStringLiteral(text?: string, location?: TextRange, flags?: NodeFlags): StringLiteral { - let node = createNode(SyntaxKind.StringLiteral, location, flags); - node.text = text; - return node; - } - export function createRegularExpressionLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.RegularExpressionLiteral, location, flags); - node.text = text; - return node; - } - export function createNoSubstitutionTemplateLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.NoSubstitutionTemplateLiteral, location, flags); - node.text = text; - return node; - } - export function createTemplateHead(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.TemplateHead, location, flags); - node.text = text; - return node; - } - export function createTemplateMiddle(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.TemplateMiddle, location, flags); - node.text = text; - return node; - } - export function createTemplateTail(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { - let node = createNode(SyntaxKind.TemplateTail, location, flags); - node.text = text; - return node; - } - export function createIdentifier(text?: string, originalKeywordKind?: SyntaxKind, location?: TextRange, flags?: NodeFlags): Identifier { - let node = createNode(SyntaxKind.Identifier, location, flags); - if (text || originalKeywordKind) { - node.text = text; - node.originalKeywordKind = originalKeywordKind; - } - return node; - } - 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); - if (left || right) { - node.left = left; - node.right = right; - } - return node; - } - export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName { - if (left !== node.left || right !== node.right) { - let newNode = createQualifiedName(left, right); - return updateFrom(node, newNode); - } - return node; - } - export function createComputedPropertyName(expression?: Expression, location?: TextRange, flags?: NodeFlags): ComputedPropertyName { - let node = createNode(SyntaxKind.ComputedPropertyName, location, flags); - node.expression = expression; - return node; - } - export function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName { - if (expression !== node.expression) { - let newNode = createComputedPropertyName(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeParameter(name?: Identifier, constraint?: TypeNode, expression?: Expression, - location?: TextRange, flags?: NodeFlags): TypeParameterDeclaration { - let node = createNode(SyntaxKind.TypeParameter, location, flags); - if (name || constraint || expression) { - node.name = name; - node.constraint = constraint; - node.expression = expression; - } - return node; - } - export function updateTypeParameter(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode, expression: Expression - ): TypeParameterDeclaration { - if (name !== node.name || constraint !== node.constraint || expression !== node.expression) { - let newNode = createTypeParameter(name, constraint, expression); - return updateFrom(node, newNode); - } - return node; - } - export function createParameter(decorators?: Array, modifiers?: Array, dotDotDotToken?: Node, - name?: BindingPattern | Identifier, questionToken?: Node, type?: TypeNode, initializer?: Expression, - location?: TextRange, flags?: NodeFlags): ParameterDeclaration { - let node = createNode(SyntaxKind.Parameter, location, flags); - if (decorators || modifiers || dotDotDotToken || name || questionToken || type || initializer) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.dotDotDotToken = dotDotDotToken; - node.name = name; - node.questionToken = questionToken; - node.type = type; - node.initializer = initializer; - } - return node; - } - export function updateParameter(node: ParameterDeclaration, decorators: Array, modifiers: Array - , name: BindingPattern | Identifier, questionToken: Node, type: TypeNode, initializer: Expression): ParameterDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || questionToken !== node.questionToken || - type !== node.type || initializer !== node.initializer) { - let newNode = createParameter(decorators, modifiers, node.dotDotDotToken, name, questionToken, type, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createDecorator(expression?: LeftHandSideExpression, location?: TextRange, flags?: NodeFlags): Decorator { - let node = createNode(SyntaxKind.Decorator, location, flags); - node.expression = expression; - return node; - } - export function updateDecorator(node: Decorator, expression: LeftHandSideExpression): Decorator { - if (expression !== node.expression) { - let newNode = createDecorator(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createPropertySignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, - type?: TypeNode, location?: TextRange, flags?: NodeFlags): PropertySignature { - let node = createNode(SyntaxKind.PropertySignature, location, flags); - if (decorators || modifiers || name || questionToken || type) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.questionToken = questionToken; - node.type = type; - } - return node; - } - export function updatePropertySignature(node: PropertySignature, decorators: Array, modifiers: Array, name: PropertyName - , type: TypeNode): PropertySignature { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type) { - let newNode = createPropertySignature(decorators, modifiers, name, node.questionToken, type); - return updateFrom(node, newNode); - } - return node; - } - export function createPropertyDeclaration(decorators?: Array, modifiers?: Array, name?: PropertyName, type?: TypeNode, - initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyDeclaration { - let node = createNode(SyntaxKind.PropertyDeclaration, location, flags); - if (decorators || modifiers || name || type || initializer) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.type = type; - node.initializer = initializer; - } - return node; - } - export function updatePropertyDeclaration(node: PropertyDeclaration, decorators: Array, modifiers: Array, name: PropertyName - , type: TypeNode, initializer: Expression): PropertyDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type || - initializer !== node.initializer) { - let newNode = createPropertyDeclaration(decorators, modifiers, name, type, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createMethodSignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, - typeParameters?: Array, parameters?: Array, type?: TypeNode, - location?: TextRange, flags?: NodeFlags): MethodSignature { - let node = createNode(SyntaxKind.MethodSignature, location, flags); - if (decorators || modifiers || name || questionToken || typeParameters || parameters || type) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.questionToken = questionToken; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - } - return node; - } - export function updateMethodSignature(node: MethodSignature, decorators: Array, modifiers: Array, name: PropertyName - , typeParameters: Array, parameters: Array, type: TypeNode): MethodSignature { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - parameters !== node.parameters || type !== node.type) { - let newNode = createMethodSignature(decorators, modifiers, name, node.questionToken, typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function createMethodDeclaration(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: PropertyName, - typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: Block, - location?: TextRange, flags?: NodeFlags): MethodDeclaration { - let node = createNode(SyntaxKind.MethodDeclaration, location, flags); - if (decorators || modifiers || asteriskToken || name || typeParameters || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.asteriskToken = asteriskToken; - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateMethodDeclaration(node: MethodDeclaration, decorators: Array, modifiers: Array, name: PropertyName - , typeParameters: Array, parameters: Array, type: TypeNode, body: Block): MethodDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - parameters !== node.parameters || type !== node.type || body !== node.body) { - let newNode = createMethodDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createConstructor(decorators?: Array, modifiers?: Array, parameters?: Array, - type?: TypeNode, body?: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration { - let node = createNode(SyntaxKind.Constructor, location, flags); - if (decorators || modifiers || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateConstructor(node: ConstructorDeclaration, decorators: Array, modifiers: Array - , parameters: Array, type: TypeNode, body: Block): ConstructorDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || parameters !== node.parameters || type !== node.type || - body !== node.body) { - let newNode = createConstructor(decorators, modifiers, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createGetAccessor(decorators?: Array, modifiers?: Array, name?: PropertyName, - parameters?: Array, type?: TypeNode, body?: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration { - let node = createNode(SyntaxKind.GetAccessor, location, flags); - if (decorators || modifiers || name || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Array, modifiers: Array, name: PropertyName - , parameters: Array, type: TypeNode, body: Block): GetAccessorDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters || - type !== node.type || body !== node.body) { - let newNode = createGetAccessor(decorators, modifiers, name, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createSetAccessor(decorators?: Array, modifiers?: Array, name?: PropertyName, - parameters?: Array, type?: TypeNode, body?: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration { - let node = createNode(SyntaxKind.SetAccessor, location, flags); - if (decorators || modifiers || name || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Array, modifiers: Array, name: PropertyName - , parameters: Array, type: TypeNode, body: Block): SetAccessorDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters || - type !== node.type || body !== node.body) { - let newNode = createSetAccessor(decorators, modifiers, name, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createCallSignature(typeParameters?: Array, parameters?: Array, type?: TypeNode, - questionToken?: Node, location?: TextRange, flags?: NodeFlags): CallSignatureDeclaration { - let node = createNode(SyntaxKind.CallSignature, location, flags); - if (typeParameters || parameters || type || questionToken) { - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.questionToken = questionToken; - } - return node; - } - export function updateCallSignature(node: CallSignatureDeclaration, typeParameters: Array - , parameters: Array, type: TypeNode): CallSignatureDeclaration { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createCallSignature(typeParameters, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function createConstructSignature(typeParameters?: Array, parameters?: Array, - type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): ConstructSignatureDeclaration { - let node = createNode(SyntaxKind.ConstructSignature, location, flags); - if (typeParameters || parameters || type || questionToken) { - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.questionToken = questionToken; - } - return node; - } - export function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: Array - , parameters: Array, type: TypeNode): ConstructSignatureDeclaration { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createConstructSignature(typeParameters, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function createIndexSignature(decorators?: Array, modifiers?: Array, parameters?: Array, - type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): IndexSignatureDeclaration { - let node = createNode(SyntaxKind.IndexSignature, location, flags); - if (decorators || modifiers || parameters || type || questionToken) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.questionToken = questionToken; - } - return node; - } - export function updateIndexSignature(node: IndexSignatureDeclaration, decorators: Array, modifiers: Array - , parameters: Array, type: TypeNode): IndexSignatureDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || parameters !== node.parameters || type !== node.type) { - let newNode = createIndexSignature(decorators, modifiers, parameters, type, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function createTypePredicate(parameterName?: Identifier, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypePredicateNode { - let node = createNode(SyntaxKind.TypePredicate, location, flags); - if (parameterName || type) { - node.parameterName = parameterName; - node.type = type; - } - return node; - } - export function updateTypePredicate(node: TypePredicateNode, parameterName: Identifier, type: TypeNode): TypePredicateNode { - if (parameterName !== node.parameterName || type !== node.type) { - let newNode = createTypePredicate(parameterName, type); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeReference(typeName?: EntityName, typeArguments?: Array, - location?: TextRange, flags?: NodeFlags): TypeReferenceNode { - let node = createNode(SyntaxKind.TypeReference, location, flags); - if (typeName || typeArguments) { - node.typeName = typeName; - node.typeArguments = typeArguments && createNodeArray(typeArguments) - } - return node; - } - export function updateTypeReference(node: TypeReferenceNode, typeName: EntityName, typeArguments: Array): TypeReferenceNode { - if (typeName !== node.typeName || typeArguments !== node.typeArguments) { - let newNode = createTypeReference(typeName, typeArguments); - return updateFrom(node, newNode); - } - return node; - } - export function createFunctionType(typeParameters?: Array, parameters?: Array, type?: TypeNode, - location?: TextRange, flags?: NodeFlags): FunctionTypeNode { - let node = createNode(SyntaxKind.FunctionType, location, flags); - if (typeParameters || parameters || type) { - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - } - return node; - } - export function updateFunctionType(node: FunctionTypeNode, typeParameters: Array - , parameters: Array, type: TypeNode): FunctionTypeNode { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createFunctionType(typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function createConstructorType(typeParameters?: Array, parameters?: Array, - type?: TypeNode, location?: TextRange, flags?: NodeFlags): ConstructorTypeNode { - let node = createNode(SyntaxKind.ConstructorType, location, flags); - if (typeParameters || parameters || type) { - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - } - return node; - } - export function updateConstructorType(node: ConstructorTypeNode, typeParameters: Array - , parameters: Array, type: TypeNode): ConstructorTypeNode { - if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { - let newNode = createConstructorType(typeParameters, parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeQuery(exprName?: EntityName, location?: TextRange, flags?: NodeFlags): TypeQueryNode { - let node = createNode(SyntaxKind.TypeQuery, location, flags); - node.exprName = exprName; - return node; - } - export function updateTypeQuery(node: TypeQueryNode, exprName: EntityName): TypeQueryNode { - if (exprName !== node.exprName) { - let newNode = createTypeQuery(exprName); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeLiteral(members?: Array, location?: TextRange, flags?: NodeFlags): TypeLiteralNode { - let node = createNode(SyntaxKind.TypeLiteral, location, flags); - node.members = members && createNodeArray(members) - return node; - } - export function updateTypeLiteral(node: TypeLiteralNode, members: Array): TypeLiteralNode { - if (members !== node.members) { - let newNode = createTypeLiteral(members); - return updateFrom(node, newNode); - } - return node; - } - export function createArrayType(elementType?: TypeNode, location?: TextRange, flags?: NodeFlags): ArrayTypeNode { - let node = createNode(SyntaxKind.ArrayType, location, flags); - node.elementType = elementType; - return node; - } - export function updateArrayType(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { - if (elementType !== node.elementType) { - let newNode = createArrayType(elementType); - return updateFrom(node, newNode); - } - return node; - } - export function createTupleType(elementTypes?: Array, location?: TextRange, flags?: NodeFlags): TupleTypeNode { - let node = createNode(SyntaxKind.TupleType, location, flags); - node.elementTypes = elementTypes && createNodeArray(elementTypes) - return node; - } - export function updateTupleType(node: TupleTypeNode, elementTypes: Array): TupleTypeNode { - if (elementTypes !== node.elementTypes) { - let newNode = createTupleType(elementTypes); - return updateFrom(node, newNode); - } - return node; - } - export function createUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): UnionTypeNode { - let node = createNode(SyntaxKind.UnionType, location, flags); - node.types = types && createNodeArray(types) - return node; - } - export function updateUnionType(node: UnionTypeNode, types: Array): UnionTypeNode { - if (types !== node.types) { - let newNode = createUnionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function createIntersectionType(types?: Array, location?: TextRange, flags?: NodeFlags): IntersectionTypeNode { - let node = createNode(SyntaxKind.IntersectionType, location, flags); - node.types = types && createNodeArray(types) - return node; - } - export function updateIntersectionType(node: IntersectionTypeNode, types: Array): IntersectionTypeNode { - if (types !== node.types) { - let newNode = createIntersectionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function createParenthesizedType(type?: TypeNode, location?: TextRange, flags?: NodeFlags): ParenthesizedTypeNode { - let node = createNode(SyntaxKind.ParenthesizedType, location, flags); - node.type = type; - return node; - } - export function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode { - if (type !== node.type) { - let newNode = createParenthesizedType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createObjectBindingPattern(elements?: Array, location?: TextRange, flags?: NodeFlags): ObjectBindingPattern { - let node = createNode(SyntaxKind.ObjectBindingPattern, location, flags); - node.elements = elements && createNodeArray(elements) - return node; - } - export function updateObjectBindingPattern(node: ObjectBindingPattern, elements: Array): ObjectBindingPattern { - if (elements !== node.elements) { - let newNode = createObjectBindingPattern(elements); - return updateFrom(node, newNode); - } - return node; - } - export function createArrayBindingPattern(elements?: Array, location?: TextRange, flags?: NodeFlags): ArrayBindingPattern { - let node = createNode(SyntaxKind.ArrayBindingPattern, location, flags); - node.elements = elements && createNodeArray(elements) - return node; - } - export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: Array): ArrayBindingPattern { - if (elements !== node.elements) { - let newNode = createArrayBindingPattern(elements); - return updateFrom(node, newNode); - } - return node; - } - export function createBindingElement(decorators?: Array, modifiers?: Array, propertyName?: Identifier, dotDotDotToken?: Node, - name?: BindingPattern | Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags): BindingElement { - let node = createNode(SyntaxKind.BindingElement, location, flags); - if (decorators || modifiers || propertyName || dotDotDotToken || name || initializer) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.propertyName = propertyName; - node.dotDotDotToken = dotDotDotToken; - node.name = name; - node.initializer = initializer; - } - return node; - } - export function updateBindingElement(node: BindingElement, decorators: Array, modifiers: Array, propertyName: Identifier - , name: BindingPattern | Identifier, initializer: Expression): BindingElement { - if (decorators !== node.decorators || modifiers !== node.modifiers || propertyName !== node.propertyName || name !== node.name || - initializer !== node.initializer) { - let newNode = createBindingElement(decorators, modifiers, propertyName, node.dotDotDotToken, name, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createArrayLiteralExpression(elements?: Array, location?: TextRange, flags?: NodeFlags): ArrayLiteralExpression { - let node = createNode(SyntaxKind.ArrayLiteralExpression, location, flags); - node.elements = elements && createNodeArray(elements) - return node; - } - export function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: Array): ArrayLiteralExpression { - if (elements !== node.elements) { - let newNode = createArrayLiteralExpression(elements); - return updateFrom(node, newNode); - } - return node; - } - export function createObjectLiteralExpression(decorators?: Array, modifiers?: Array, properties?: Array, - location?: TextRange, flags?: NodeFlags): ObjectLiteralExpression { - let node = createNode(SyntaxKind.ObjectLiteralExpression, location, flags); - if (decorators || modifiers || properties) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.properties = properties && createNodeArray(properties) - } - return node; - } - export function updateObjectLiteralExpression(node: ObjectLiteralExpression, decorators: Array, modifiers: Array - , properties: Array): ObjectLiteralExpression { - if (decorators !== node.decorators || modifiers !== node.modifiers || properties !== node.properties) { - let newNode = createObjectLiteralExpression(decorators, modifiers, properties); - return updateFrom(node, newNode); - } - return node; - } - export function createPropertyAccessExpression(expression?: LeftHandSideExpression, dotToken?: Node, name?: Identifier, - location?: TextRange, flags?: NodeFlags): PropertyAccessExpression { - let node = createNode(SyntaxKind.PropertyAccessExpression, location, flags); - if (expression || dotToken || name) { - node.expression = expression; - node.dotToken = dotToken; - node.name = name; - } - return node; - } - export function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: LeftHandSideExpression, name: Identifier - ): PropertyAccessExpression { - if (expression !== node.expression || name !== node.name) { - let newNode = createPropertyAccessExpression(expression, node.dotToken, name); - return updateFrom(node, newNode); - } - return node; - } - export function createElementAccessExpression(expression?: LeftHandSideExpression, argumentExpression?: Expression, - location?: TextRange, flags?: NodeFlags): ElementAccessExpression { - let node = createNode(SyntaxKind.ElementAccessExpression, location, flags); - if (expression || argumentExpression) { - node.expression = expression; - node.argumentExpression = argumentExpression; - } - return node; - } - export function updateElementAccessExpression(node: ElementAccessExpression, expression: LeftHandSideExpression, argumentExpression: Expression - ): ElementAccessExpression { - if (expression !== node.expression || argumentExpression !== node.argumentExpression) { - let newNode = createElementAccessExpression(expression, argumentExpression); - return updateFrom(node, newNode); - } - return node; - } - export function createCallExpression(expression?: LeftHandSideExpression, typeArguments?: Array, _arguments?: Array, - location?: TextRange, flags?: NodeFlags): CallExpression { - let node = createNode(SyntaxKind.CallExpression, location, flags); - if (expression || typeArguments || _arguments) { - node.expression = expression; - node.typeArguments = typeArguments && createNodeArray(typeArguments) - node.arguments = _arguments && createNodeArray(_arguments) - } - return node; - } - export function updateCallExpression(node: CallExpression, expression: LeftHandSideExpression, typeArguments: Array - , _arguments: Array): CallExpression { - if (expression !== node.expression || typeArguments !== node.typeArguments || _arguments !== node.arguments) { - let newNode = createCallExpression(expression, typeArguments, _arguments); - return updateFrom(node, newNode); - } - return node; - } - export function createNewExpression(expression?: LeftHandSideExpression, typeArguments?: Array, _arguments?: Array, - location?: TextRange, flags?: NodeFlags): NewExpression { - let node = createNode(SyntaxKind.NewExpression, location, flags); - if (expression || typeArguments || _arguments) { - node.expression = expression; - node.typeArguments = typeArguments && createNodeArray(typeArguments) - node.arguments = _arguments && createNodeArray(_arguments) - } - return node; - } - export function updateNewExpression(node: NewExpression, expression: LeftHandSideExpression, typeArguments: Array - , _arguments: Array): NewExpression { - if (expression !== node.expression || typeArguments !== node.typeArguments || _arguments !== node.arguments) { - let newNode = createNewExpression(expression, typeArguments, _arguments); - return updateFrom(node, newNode); - } - return node; - } - export function createTaggedTemplateExpression(tag?: LeftHandSideExpression, template?: LiteralExpression | TemplateExpression, - location?: TextRange, flags?: NodeFlags): TaggedTemplateExpression { - let node = createNode(SyntaxKind.TaggedTemplateExpression, location, flags); - if (tag || template) { - node.tag = tag; - node.template = template; - } - return node; - } - export function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: LeftHandSideExpression - , template: LiteralExpression | TemplateExpression): TaggedTemplateExpression { - if (tag !== node.tag || template !== node.template) { - let newNode = createTaggedTemplateExpression(tag, template); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeAssertionExpression(type?: TypeNode, expression?: UnaryExpression, - location?: TextRange, flags?: NodeFlags): TypeAssertion { - let node = createNode(SyntaxKind.TypeAssertionExpression, location, flags); - if (type || expression) { - node.type = type; - node.expression = expression; - } - return node; - } - export function updateTypeAssertionExpression(node: TypeAssertion, type: TypeNode, expression: UnaryExpression): TypeAssertion { - if (type !== node.type || expression !== node.expression) { - let newNode = createTypeAssertionExpression(type, expression); - return updateFrom(node, newNode); - } - return node; - } - export function createParenthesizedExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): ParenthesizedExpression { - let node = createNode(SyntaxKind.ParenthesizedExpression, location, flags); - node.expression = expression; - return node; - } - export function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression { - if (expression !== node.expression) { - let newNode = createParenthesizedExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createFunctionExpression(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: Identifier, - typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: Block | Expression, - location?: TextRange, flags?: NodeFlags): FunctionExpression { - let node = createNode(SyntaxKind.FunctionExpression, location, flags); - if (decorators || modifiers || asteriskToken || name || typeParameters || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.asteriskToken = asteriskToken; - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateFunctionExpression(node: FunctionExpression, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, parameters: Array, type: TypeNode, body: Block | Expression - ): FunctionExpression { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - parameters !== node.parameters || type !== node.type || body !== node.body) { - let newNode = createFunctionExpression(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createArrowFunction(decorators?: Array, modifiers?: Array, typeParameters?: Array, - parameters?: Array, type?: TypeNode, equalsGreaterThanToken?: Node, body?: Block | Expression, - location?: TextRange, flags?: NodeFlags): ArrowFunction { - let node = createNode(SyntaxKind.ArrowFunction, location, flags); - if (decorators || modifiers || typeParameters || parameters || type || equalsGreaterThanToken || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.equalsGreaterThanToken = equalsGreaterThanToken; - node.body = body; - } - return node; - } - export function updateArrowFunction(node: ArrowFunction, decorators: Array, modifiers: Array - , typeParameters: Array, parameters: Array, type: TypeNode, body: Block | Expression - ): ArrowFunction { - if (decorators !== node.decorators || modifiers !== node.modifiers || typeParameters !== node.typeParameters || - parameters !== node.parameters || type !== node.type || body !== node.body) { - let newNode = createArrowFunction(decorators, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body); - return updateFrom(node, newNode); - } - return node; - } - export function createDeleteExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): DeleteExpression { - let node = createNode(SyntaxKind.DeleteExpression, location, flags); - node.expression = expression; - return node; - } - export function updateDeleteExpression(node: DeleteExpression, expression: UnaryExpression): DeleteExpression { - if (expression !== node.expression) { - let newNode = createDeleteExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeOfExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): TypeOfExpression { - let node = createNode(SyntaxKind.TypeOfExpression, location, flags); - node.expression = expression; - return node; - } - export function updateTypeOfExpression(node: TypeOfExpression, expression: UnaryExpression): TypeOfExpression { - if (expression !== node.expression) { - let newNode = createTypeOfExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createVoidExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): VoidExpression { - let node = createNode(SyntaxKind.VoidExpression, location, flags); - node.expression = expression; - return node; - } - export function updateVoidExpression(node: VoidExpression, expression: UnaryExpression): VoidExpression { - if (expression !== node.expression) { - let newNode = createVoidExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createAwaitExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): AwaitExpression { - let node = createNode(SyntaxKind.AwaitExpression, location, flags); - node.expression = expression; - return node; - } - export function updateAwaitExpression(node: AwaitExpression, expression: UnaryExpression): AwaitExpression { - if (expression !== node.expression) { - let newNode = createAwaitExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createPrefixUnaryExpression(operator?: SyntaxKind, operand?: UnaryExpression, - location?: TextRange, flags?: NodeFlags): PrefixUnaryExpression { - let node = createNode(SyntaxKind.PrefixUnaryExpression, location, flags); - if (operator || operand) { - node.operator = operator; - node.operand = operand; - } - return node; - } - export function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: UnaryExpression): PrefixUnaryExpression { - if (operand !== node.operand) { - let newNode = createPrefixUnaryExpression(node.operator, operand); - return updateFrom(node, newNode); - } - return node; - } - export function createPostfixUnaryExpression(operand?: LeftHandSideExpression, operator?: SyntaxKind, - location?: TextRange, flags?: NodeFlags): PostfixUnaryExpression { - let node = createNode(SyntaxKind.PostfixUnaryExpression, location, flags); - if (operand || operator) { - node.operand = operand; - node.operator = operator; - } - return node; - } - export function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: LeftHandSideExpression): PostfixUnaryExpression { - if (operand !== node.operand) { - let newNode = createPostfixUnaryExpression(operand, node.operator); - return updateFrom(node, newNode); - } - return node; - } - export function createBinaryExpression(left?: Expression, operatorToken?: Node, right?: Expression, - location?: TextRange, flags?: NodeFlags): BinaryExpression { - let node = createNode(SyntaxKind.BinaryExpression, location, flags); - if (left || operatorToken || right) { - node.left = left; - node.operatorToken = operatorToken; - node.right = right; - } - return node; - } - export function updateBinaryExpression(node: BinaryExpression, left: Expression, right: Expression): BinaryExpression { - if (left !== node.left || right !== node.right) { - let newNode = createBinaryExpression(left, node.operatorToken, right); - return updateFrom(node, newNode); - } - return node; - } - export function createConditionalExpression(condition?: Expression, questionToken?: Node, whenTrue?: Expression, colonToken?: Node, - whenFalse?: Expression, location?: TextRange, flags?: NodeFlags): ConditionalExpression { - let node = createNode(SyntaxKind.ConditionalExpression, location, flags); - if (condition || questionToken || whenTrue || colonToken || whenFalse) { - node.condition = condition; - node.questionToken = questionToken; - node.whenTrue = whenTrue; - node.colonToken = colonToken; - node.whenFalse = whenFalse; - } - return node; - } - export function updateConditionalExpression(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression - ): ConditionalExpression { - if (condition !== node.condition || whenTrue !== node.whenTrue || whenFalse !== node.whenFalse) { - let newNode = createConditionalExpression(condition, node.questionToken, whenTrue, node.colonToken, whenFalse); - return updateFrom(node, newNode); - } - return node; - } - export function createTemplateExpression(head?: LiteralExpression, templateSpans?: Array, - location?: TextRange, flags?: NodeFlags): TemplateExpression { - let node = createNode(SyntaxKind.TemplateExpression, location, flags); - if (head || templateSpans) { - node.head = head; - node.templateSpans = templateSpans && createNodeArray(templateSpans) - } - return node; - } - export function updateTemplateExpression(node: TemplateExpression, head: LiteralExpression, templateSpans: Array - ): TemplateExpression { - if (head !== node.head || templateSpans !== node.templateSpans) { - let newNode = createTemplateExpression(head, templateSpans); - return updateFrom(node, newNode); - } - return node; - } - export function createYieldExpression(asteriskToken?: Node, expression?: Expression, location?: TextRange, flags?: NodeFlags): YieldExpression { - let node = createNode(SyntaxKind.YieldExpression, location, flags); - if (asteriskToken || expression) { - node.asteriskToken = asteriskToken; - node.expression = expression; - } - return node; - } - export function updateYieldExpression(node: YieldExpression, expression: Expression): YieldExpression { - if (expression !== node.expression) { - let newNode = createYieldExpression(node.asteriskToken, expression); - return updateFrom(node, newNode); - } - return node; - } - export function createSpreadElementExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): SpreadElementExpression { - let node = createNode(SyntaxKind.SpreadElementExpression, location, flags); - node.expression = expression; - return node; - } - export function updateSpreadElementExpression(node: SpreadElementExpression, expression: Expression): SpreadElementExpression { - if (expression !== node.expression) { - let newNode = createSpreadElementExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createClassExpression(decorators?: Array, modifiers?: Array, name?: Identifier, - typeParameters?: Array, heritageClauses?: Array, members?: Array, - location?: TextRange, flags?: NodeFlags): ClassExpression { - let node = createNode(SyntaxKind.ClassExpression, location, flags); - if (decorators || modifiers || name || typeParameters || heritageClauses || members) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.heritageClauses = heritageClauses && createNodeArray(heritageClauses) - node.members = members && createNodeArray(members) - } - return node; - } - export function updateClassExpression(node: ClassExpression, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, heritageClauses: Array, members: Array): ClassExpression { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - heritageClauses !== node.heritageClauses || members !== node.members) { - let newNode = createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members); - return updateFrom(node, newNode); - } - return node; - } - export function createOmittedExpression(location?: TextRange, flags?: NodeFlags): Expression { - return createNode(SyntaxKind.OmittedExpression, location, flags); - } - export function createExpressionWithTypeArguments(expression?: LeftHandSideExpression, typeArguments?: Array, - location?: TextRange, flags?: NodeFlags): ExpressionWithTypeArguments { - let node = createNode(SyntaxKind.ExpressionWithTypeArguments, location, flags); - if (expression || typeArguments) { - node.expression = expression; - node.typeArguments = typeArguments && createNodeArray(typeArguments) - } - return node; - } - export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: LeftHandSideExpression - , typeArguments: Array): ExpressionWithTypeArguments { - if (expression !== node.expression || typeArguments !== node.typeArguments) { - let newNode = createExpressionWithTypeArguments(expression, typeArguments); - return updateFrom(node, newNode); - } - return node; - } - export function createAsExpression(expression?: Expression, type?: TypeNode, location?: TextRange, flags?: NodeFlags): AsExpression { - let node = createNode(SyntaxKind.AsExpression, location, flags); - if (expression || type) { - node.expression = expression; - node.type = type; - } - return node; - } - export function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression { - if (expression !== node.expression || type !== node.type) { - let newNode = createAsExpression(expression, type); - return updateFrom(node, newNode); - } - return node; - } - export function createTemplateSpan(expression?: Expression, literal?: LiteralExpression, location?: TextRange, flags?: NodeFlags): TemplateSpan { - let node = createNode(SyntaxKind.TemplateSpan, location, flags); - if (expression || literal) { - node.expression = expression; - node.literal = literal; - } - return node; - } - export function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: LiteralExpression): TemplateSpan { - if (expression !== node.expression || literal !== node.literal) { - let newNode = createTemplateSpan(expression, literal); - return updateFrom(node, newNode); - } - return node; - } - export function createSemicolonClassElement(location?: TextRange, flags?: NodeFlags): SemicolonClassElement { - return createNode(SyntaxKind.SemicolonClassElement, location, flags); - } - export function createBlock(statements?: Array, location?: TextRange, flags?: NodeFlags): Block { - let node = createNode(SyntaxKind.Block, location, flags); - node.statements = statements && createNodeArray(statements) - return node; - } - export function updateBlock(node: Block, statements: Array): Block { - if (statements !== node.statements) { - let newNode = createBlock(statements); - return updateFrom(node, newNode); - } - return node; - } - export function createVariableStatement(decorators?: Array, modifiers?: Array, declarationList?: VariableDeclarationList, - location?: TextRange, flags?: NodeFlags): VariableStatement { - let node = createNode(SyntaxKind.VariableStatement, location, flags); - if (decorators || modifiers || declarationList) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.declarationList = declarationList; - } - return node; - } - 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; - } - export function createEmptyStatement(location?: TextRange, flags?: NodeFlags): EmptyStatement { - return createNode(SyntaxKind.EmptyStatement, location, flags); - } - export function createExpressionStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ExpressionStatement { - let node = createNode(SyntaxKind.ExpressionStatement, location, flags); - node.expression = expression; - return node; - } - export function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement { - if (expression !== node.expression) { - let newNode = createExpressionStatement(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createIfStatement(expression?: Expression, thenStatement?: Statement, elseStatement?: Statement, - location?: TextRange, flags?: NodeFlags): IfStatement { - let node = createNode(SyntaxKind.IfStatement, location, flags); - if (expression || thenStatement || elseStatement) { - node.expression = expression; - node.thenStatement = thenStatement; - node.elseStatement = elseStatement; - } - return node; - } - export function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement): IfStatement { - if (expression !== node.expression || thenStatement !== node.thenStatement || elseStatement !== node.elseStatement) { - let newNode = createIfStatement(expression, thenStatement, elseStatement); - return updateFrom(node, newNode); - } - return node; - } - export function createDoStatement(statement?: Statement, expression?: Expression, location?: TextRange, flags?: NodeFlags): DoStatement { - let node = createNode(SyntaxKind.DoStatement, location, flags); - if (statement || expression) { - node.statement = statement; - node.expression = expression; - } - return node; - } - export function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression): DoStatement { - if (statement !== node.statement || expression !== node.expression) { - let newNode = createDoStatement(statement, expression); - return updateFrom(node, newNode); - } - return node; - } - export function createWhileStatement(expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): WhileStatement { - let node = createNode(SyntaxKind.WhileStatement, location, flags); - if (expression || statement) { - node.expression = expression; - node.statement = statement; - } - return node; - } - export function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement { - if (expression !== node.expression || statement !== node.statement) { - let newNode = createWhileStatement(expression, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createForStatement(initializer?: Expression | VariableDeclarationList, condition?: Expression, incrementor?: Expression, - statement?: Statement, location?: TextRange, flags?: NodeFlags): ForStatement { - let node = createNode(SyntaxKind.ForStatement, location, flags); - if (initializer || condition || incrementor || statement) { - node.initializer = initializer; - node.condition = condition; - node.incrementor = incrementor; - node.statement = statement; - } - return node; - } - export function updateForStatement(node: ForStatement, initializer: Expression | VariableDeclarationList, condition: Expression - , incrementor: Expression, statement: Statement): ForStatement { - if (initializer !== node.initializer || condition !== node.condition || incrementor !== node.incrementor || statement !== node.statement) { - let newNode = createForStatement(initializer, condition, incrementor, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createForInStatement(initializer?: Expression | VariableDeclarationList, expression?: Expression, statement?: Statement, - location?: TextRange, flags?: NodeFlags): ForInStatement { - let node = createNode(SyntaxKind.ForInStatement, location, flags); - if (initializer || expression || statement) { - node.initializer = initializer; - node.expression = expression; - node.statement = statement; - } - return node; - } - export function updateForInStatement(node: ForInStatement, initializer: Expression | VariableDeclarationList, expression: Expression - , statement: Statement): ForInStatement { - if (initializer !== node.initializer || expression !== node.expression || statement !== node.statement) { - let newNode = createForInStatement(initializer, expression, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createForOfStatement(initializer?: Expression | VariableDeclarationList, expression?: Expression, statement?: Statement, - location?: TextRange, flags?: NodeFlags): ForOfStatement { - let node = createNode(SyntaxKind.ForOfStatement, location, flags); - if (initializer || expression || statement) { - node.initializer = initializer; - node.expression = expression; - node.statement = statement; - } - return node; - } - export function updateForOfStatement(node: ForOfStatement, initializer: Expression | VariableDeclarationList, expression: Expression - , statement: Statement): ForOfStatement { - if (initializer !== node.initializer || expression !== node.expression || statement !== node.statement) { - let newNode = createForOfStatement(initializer, expression, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createContinueStatement(label?: Identifier, location?: TextRange, flags?: NodeFlags): ContinueStatement { - let node = createNode(SyntaxKind.ContinueStatement, location, flags); - node.label = label; - return node; - } - export function updateContinueStatement(node: ContinueStatement, label: Identifier): ContinueStatement { - if (label !== node.label) { - let newNode = createContinueStatement(label); - return updateFrom(node, newNode); - } - return node; - } - export function createBreakStatement(label?: Identifier, location?: TextRange, flags?: NodeFlags): BreakStatement { - let node = createNode(SyntaxKind.BreakStatement, location, flags); - node.label = label; - return node; - } - export function updateBreakStatement(node: BreakStatement, label: Identifier): BreakStatement { - if (label !== node.label) { - let newNode = createBreakStatement(label); - return updateFrom(node, newNode); - } - return node; - } - export function createReturnStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ReturnStatement { - let node = createNode(SyntaxKind.ReturnStatement, location, flags); - node.expression = expression; - return node; - } - export function updateReturnStatement(node: ReturnStatement, expression: Expression): ReturnStatement { - if (expression !== node.expression) { - let newNode = createReturnStatement(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createWithStatement(expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): WithStatement { - let node = createNode(SyntaxKind.WithStatement, location, flags); - if (expression || statement) { - node.expression = expression; - node.statement = statement; - } - return node; - } - export function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement): WithStatement { - if (expression !== node.expression || statement !== node.statement) { - let newNode = createWithStatement(expression, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createSwitchStatement(expression?: Expression, caseBlock?: CaseBlock, location?: TextRange, flags?: NodeFlags): SwitchStatement { - let node = createNode(SyntaxKind.SwitchStatement, location, flags); - if (expression || caseBlock) { - node.expression = expression; - node.caseBlock = caseBlock; - } - return node; - } - export function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement { - if (expression !== node.expression || caseBlock !== node.caseBlock) { - let newNode = createSwitchStatement(expression, caseBlock); - return updateFrom(node, newNode); - } - return node; - } - export function createLabeledStatement(label?: Identifier, statement?: Statement, location?: TextRange, flags?: NodeFlags): LabeledStatement { - let node = createNode(SyntaxKind.LabeledStatement, location, flags); - if (label || statement) { - node.label = label; - node.statement = statement; - } - return node; - } - export function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement { - if (label !== node.label || statement !== node.statement) { - let newNode = createLabeledStatement(label, statement); - return updateFrom(node, newNode); - } - return node; - } - export function createThrowStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ThrowStatement { - let node = createNode(SyntaxKind.ThrowStatement, location, flags); - node.expression = expression; - return node; - } - export function updateThrowStatement(node: ThrowStatement, expression: Expression): ThrowStatement { - if (expression !== node.expression) { - let newNode = createThrowStatement(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createTryStatement(tryBlock?: Block, catchClause?: CatchClause, finallyBlock?: Block, - location?: TextRange, flags?: NodeFlags): TryStatement { - let node = createNode(SyntaxKind.TryStatement, location, flags); - if (tryBlock || catchClause || finallyBlock) { - node.tryBlock = tryBlock; - node.catchClause = catchClause; - node.finallyBlock = finallyBlock; - } - return node; - } - export function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block): TryStatement { - if (tryBlock !== node.tryBlock || catchClause !== node.catchClause || finallyBlock !== node.finallyBlock) { - let newNode = createTryStatement(tryBlock, catchClause, finallyBlock); - return updateFrom(node, newNode); - } - return node; - } - export function createDebuggerStatement(location?: TextRange, flags?: NodeFlags): DebuggerStatement { - return createNode(SyntaxKind.DebuggerStatement, location, flags); - } - export function createVariableDeclaration(name?: BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, - location?: TextRange, flags?: NodeFlags): VariableDeclaration { - let node = createNode(SyntaxKind.VariableDeclaration, location, flags); - if (name || type || initializer) { - node.name = name; - node.type = type; - node.initializer = initializer; - } - return node; - } - 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; - } - export function createVariableDeclarationList(declarations?: Array, - location?: TextRange, flags?: NodeFlags): VariableDeclarationList { - let node = createNode(SyntaxKind.VariableDeclarationList, location, flags); - node.declarations = declarations && createNodeArray(declarations) - return node; - } - export function updateVariableDeclarationList(node: VariableDeclarationList, declarations: Array): VariableDeclarationList { - if (declarations !== node.declarations) { - let newNode = createVariableDeclarationList(declarations); - return updateFrom(node, newNode); - } - return node; - } - export function createFunctionDeclaration(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: Identifier, - typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: Block, - location?: TextRange, flags?: NodeFlags): FunctionDeclaration { - let node = createNode(SyntaxKind.FunctionDeclaration, location, flags); - if (decorators || modifiers || asteriskToken || name || typeParameters || parameters || type || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.asteriskToken = asteriskToken; - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - node.body = body; - } - return node; - } - export function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, parameters: Array, type: TypeNode, body: Block - ): FunctionDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - parameters !== node.parameters || type !== node.type || body !== node.body) { - let newNode = createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); - return updateFrom(node, newNode); - } - return node; - } - export function createClassDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, - typeParameters?: Array, heritageClauses?: Array, members?: Array, - location?: TextRange, flags?: NodeFlags): ClassDeclaration { - let node = createNode(SyntaxKind.ClassDeclaration, location, flags); - if (decorators || modifiers || name || typeParameters || heritageClauses || members) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.heritageClauses = heritageClauses && createNodeArray(heritageClauses) - node.members = members && createNodeArray(members) - } - return node; - } - export function updateClassDeclaration(node: ClassDeclaration, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, heritageClauses: Array, members: Array): ClassDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - heritageClauses !== node.heritageClauses || members !== node.members) { - let newNode = createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); - return updateFrom(node, newNode); - } - return node; - } - export function createInterfaceDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, - typeParameters?: Array, heritageClauses?: Array, members?: Array, - location?: TextRange, flags?: NodeFlags): InterfaceDeclaration { - let node = createNode(SyntaxKind.InterfaceDeclaration, location, flags); - if (decorators || modifiers || name || typeParameters || heritageClauses || members) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.heritageClauses = heritageClauses && createNodeArray(heritageClauses) - node.members = members && createNodeArray(members) - } - return node; - } - export function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, heritageClauses: Array, members: Array - ): InterfaceDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - heritageClauses !== node.heritageClauses || members !== node.members) { - let newNode = createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); - return updateFrom(node, newNode); - } - return node; - } - export function createTypeAliasDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, - typeParameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypeAliasDeclaration { - let node = createNode(SyntaxKind.TypeAliasDeclaration, location, flags); - if (decorators || modifiers || name || typeParameters || type) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.type = type; - } - return node; - } - export function updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: Array, modifiers: Array, name: Identifier - , typeParameters: Array, type: TypeNode): TypeAliasDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || - type !== node.type) { - let newNode = createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function createEnumDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, members?: Array, - location?: TextRange, flags?: NodeFlags): EnumDeclaration { - let node = createNode(SyntaxKind.EnumDeclaration, location, flags); - if (decorators || modifiers || name || members) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.members = members && createNodeArray(members) - } - return node; - } - export function updateEnumDeclaration(node: EnumDeclaration, decorators: Array, modifiers: Array, name: Identifier - , members: Array): EnumDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || members !== node.members) { - let newNode = createEnumDeclaration(decorators, modifiers, name, members); - return updateFrom(node, newNode); - } - return node; - } - export function createModuleDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier | LiteralExpression, - body?: ModuleBlock | ModuleDeclaration, location?: TextRange, flags?: NodeFlags): ModuleDeclaration { - let node = createNode(SyntaxKind.ModuleDeclaration, location, flags); - if (decorators || modifiers || name || body) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.body = body; - } - return node; - } - export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Array, modifiers: Array - , name: Identifier | LiteralExpression, body: ModuleBlock | ModuleDeclaration): ModuleDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || body !== node.body) { - let newNode = createModuleDeclaration(decorators, modifiers, name, body); - return updateFrom(node, newNode); - } - return node; - } - export function createModuleBlock(statements?: Array, location?: TextRange, flags?: NodeFlags): ModuleBlock { - let node = createNode(SyntaxKind.ModuleBlock, location, flags); - node.statements = statements && createNodeArray(statements) - return node; - } - export function updateModuleBlock(node: ModuleBlock, statements: Array): ModuleBlock { - if (statements !== node.statements) { - let newNode = createModuleBlock(statements); - return updateFrom(node, newNode); - } - return node; - } - export function createCaseBlock(clauses?: Array, location?: TextRange, flags?: NodeFlags): CaseBlock { - let node = createNode(SyntaxKind.CaseBlock, location, flags); - node.clauses = clauses && createNodeArray(clauses) - return node; - } - export function updateCaseBlock(node: CaseBlock, clauses: Array): CaseBlock { - if (clauses !== node.clauses) { - let newNode = createCaseBlock(clauses); - return updateFrom(node, newNode); - } - return node; - } - export function createImportEqualsDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, - moduleReference?: EntityName | ExternalModuleReference, location?: TextRange, flags?: NodeFlags): ImportEqualsDeclaration { - let node = createNode(SyntaxKind.ImportEqualsDeclaration, location, flags); - if (decorators || modifiers || name || moduleReference) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.name = name; - node.moduleReference = moduleReference; - } - return node; - } - export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Array, modifiers: Array - , name: Identifier, moduleReference: EntityName | ExternalModuleReference): ImportEqualsDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || moduleReference !== node.moduleReference) { - let newNode = createImportEqualsDeclaration(decorators, modifiers, name, moduleReference); - return updateFrom(node, newNode); - } - return node; - } - export function createImportDeclaration(decorators?: Array, modifiers?: Array, importClause?: ImportClause, - moduleSpecifier?: Expression, location?: TextRange, flags?: NodeFlags): ImportDeclaration { - let node = createNode(SyntaxKind.ImportDeclaration, location, flags); - if (decorators || modifiers || importClause || moduleSpecifier) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.importClause = importClause; - node.moduleSpecifier = moduleSpecifier; - } - return node; - } - export function updateImportDeclaration(node: ImportDeclaration, decorators: Array, modifiers: Array, importClause: ImportClause - , moduleSpecifier: Expression): ImportDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || importClause !== node.importClause || - moduleSpecifier !== node.moduleSpecifier) { - let newNode = createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier); - return updateFrom(node, newNode); - } - return node; - } - export function createImportClause(name?: Identifier, namedBindings?: NamedImports | NamespaceImport, - location?: TextRange, flags?: NodeFlags): ImportClause { - let node = createNode(SyntaxKind.ImportClause, location, flags); - if (name || namedBindings) { - node.name = name; - node.namedBindings = namedBindings; - } - return node; - } - export function updateImportClause(node: ImportClause, name: Identifier, namedBindings: NamedImports | NamespaceImport): ImportClause { - if (name !== node.name || namedBindings !== node.namedBindings) { - let newNode = createImportClause(name, namedBindings); - return updateFrom(node, newNode); - } - return node; - } - export function createNamespaceImport(name?: Identifier, location?: TextRange, flags?: NodeFlags): NamespaceImport { - let node = createNode(SyntaxKind.NamespaceImport, location, flags); - node.name = name; - return node; - } - export function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport { - if (name !== node.name) { - let newNode = createNamespaceImport(name); - return updateFrom(node, newNode); - } - return node; - } - export function createNamedImports(elements?: Array, location?: TextRange, flags?: NodeFlags): NamedImports { - let node = createNode(SyntaxKind.NamedImports, location, flags); - node.elements = elements && createNodeArray(elements) - return node; - } - export function updateNamedImports(node: NamedImports, elements: Array): NamedImports { - if (elements !== node.elements) { - let newNode = createNamedImports(elements); - return updateFrom(node, newNode); - } - return node; - } - export function createImportSpecifier(propertyName?: Identifier, name?: Identifier, location?: TextRange, flags?: NodeFlags): ImportSpecifier { - let node = createNode(SyntaxKind.ImportSpecifier, location, flags); - if (propertyName || name) { - node.propertyName = propertyName; - node.name = name; - } - return node; - } - export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier): ImportSpecifier { - if (propertyName !== node.propertyName || name !== node.name) { - let newNode = createImportSpecifier(propertyName, name); - return updateFrom(node, newNode); - } - return node; - } - export function createExportAssignment(decorators?: Array, modifiers?: Array, expression?: Expression, - location?: TextRange, flags?: NodeFlags): ExportAssignment { - let node = createNode(SyntaxKind.ExportAssignment, location, flags); - if (decorators || modifiers || expression) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.expression = expression; - } - return node; - } - export function updateExportAssignment(node: ExportAssignment, decorators: Array, modifiers: Array, expression: Expression - ): ExportAssignment { - if (decorators !== node.decorators || modifiers !== node.modifiers || expression !== node.expression) { - let newNode = createExportAssignment(decorators, modifiers, expression); - return updateFrom(node, newNode); - } - return node; - } - export function createExportDeclaration(decorators?: Array, modifiers?: Array, exportClause?: NamedExports, - moduleSpecifier?: Expression, location?: TextRange, flags?: NodeFlags): ExportDeclaration { - let node = createNode(SyntaxKind.ExportDeclaration, location, flags); - if (decorators || modifiers || exportClause || moduleSpecifier) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.exportClause = exportClause; - node.moduleSpecifier = moduleSpecifier; - } - return node; - } - export function updateExportDeclaration(node: ExportDeclaration, decorators: Array, modifiers: Array, exportClause: NamedExports - , moduleSpecifier: Expression): ExportDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers || exportClause !== node.exportClause || - moduleSpecifier !== node.moduleSpecifier) { - let newNode = createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier); - return updateFrom(node, newNode); - } - return node; - } - export function createNamedExports(elements?: Array, location?: TextRange, flags?: NodeFlags): NamedExports { - let node = createNode(SyntaxKind.NamedExports, location, flags); - node.elements = elements && createNodeArray(elements) - return node; - } - export function updateNamedExports(node: NamedExports, elements: Array): NamedExports { - if (elements !== node.elements) { - let newNode = createNamedExports(elements); - return updateFrom(node, newNode); - } - return node; - } - export function createExportSpecifier(propertyName?: Identifier, name?: Identifier, location?: TextRange, flags?: NodeFlags): ExportSpecifier { - let node = createNode(SyntaxKind.ExportSpecifier, location, flags); - if (propertyName || name) { - node.propertyName = propertyName; - node.name = name; - } - return node; - } - export function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier, name: Identifier): ExportSpecifier { - if (propertyName !== node.propertyName || name !== node.name) { - let newNode = createExportSpecifier(propertyName, name); - return updateFrom(node, newNode); - } - return node; - } - export function createMissingDeclaration(decorators?: Array, modifiers?: Array, questionToken?: Node, - location?: TextRange, flags?: NodeFlags): MissingDeclaration { - let node = createNode(SyntaxKind.MissingDeclaration, location, flags); - if (decorators || modifiers || questionToken) { - node.decorators = decorators && createNodeArray(decorators) - setModifiers(node, modifiers); - node.questionToken = questionToken; - } - return node; - } - export function updateMissingDeclaration(node: MissingDeclaration, decorators: Array, modifiers: Array): MissingDeclaration { - if (decorators !== node.decorators || modifiers !== node.modifiers) { - let newNode = createMissingDeclaration(decorators, modifiers, node.questionToken); - return updateFrom(node, newNode); - } - return node; - } - export function createExternalModuleReference(expression?: Expression, location?: TextRange, flags?: NodeFlags): ExternalModuleReference { - let node = createNode(SyntaxKind.ExternalModuleReference, location, flags); - node.expression = expression; - return node; - } - export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference { - if (expression !== node.expression) { - let newNode = createExternalModuleReference(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxElement(openingElement?: JsxOpeningElement, children?: Array, closingElement?: JsxClosingElement, - location?: TextRange, flags?: NodeFlags): JsxElement { - let node = createNode(SyntaxKind.JsxElement, location, flags); - if (openingElement || children || closingElement) { - node.openingElement = openingElement; - node.children = children && createNodeArray(children) - node.closingElement = closingElement; - } - return node; - } - export function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: Array - , closingElement: JsxClosingElement): JsxElement { - if (openingElement !== node.openingElement || children !== node.children || closingElement !== node.closingElement) { - let newNode = createJsxElement(openingElement, children, closingElement); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxSelfClosingElement(tagName?: EntityName, attributes?: Array, - location?: TextRange, flags?: NodeFlags): JsxSelfClosingElement { - let node = createNode(SyntaxKind.JsxSelfClosingElement, location, flags); - if (tagName || attributes) { - node.tagName = tagName; - node.attributes = attributes && createNodeArray(attributes) - } - return node; - } - export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: EntityName - , attributes: Array): JsxSelfClosingElement { - if (tagName !== node.tagName || attributes !== node.attributes) { - let newNode = createJsxSelfClosingElement(tagName, attributes); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxOpeningElement(tagName?: EntityName, attributes?: Array, - location?: TextRange, flags?: NodeFlags): JsxOpeningElement { - let node = createNode(SyntaxKind.JsxOpeningElement, location, flags); - if (tagName || attributes) { - node.tagName = tagName; - node.attributes = attributes && createNodeArray(attributes) - } - return node; - } - export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: EntityName, attributes: Array - ): JsxOpeningElement { - if (tagName !== node.tagName || attributes !== node.attributes) { - let newNode = createJsxOpeningElement(tagName, attributes); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxText(location?: TextRange, flags?: NodeFlags): JsxText { - return createNode(SyntaxKind.JsxText, location, flags); - } - export function createJsxClosingElement(tagName?: EntityName, location?: TextRange, flags?: NodeFlags): JsxClosingElement { - let node = createNode(SyntaxKind.JsxClosingElement, location, flags); - node.tagName = tagName; - return node; - } - export function updateJsxClosingElement(node: JsxClosingElement, tagName: EntityName): JsxClosingElement { - if (tagName !== node.tagName) { - let newNode = createJsxClosingElement(tagName); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxAttribute(name?: Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags): JsxAttribute { - let node = createNode(SyntaxKind.JsxAttribute, location, flags); - if (name || initializer) { - node.name = name; - node.initializer = initializer; - } - return node; - } - export function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: Expression): JsxAttribute { - if (name !== node.name || initializer !== node.initializer) { - let newNode = createJsxAttribute(name, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxSpreadAttribute(expression?: Expression, location?: TextRange, flags?: NodeFlags): JsxSpreadAttribute { - let node = createNode(SyntaxKind.JsxSpreadAttribute, location, flags); - node.expression = expression; - return node; - } - export function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute { - if (expression !== node.expression) { - let newNode = createJsxSpreadAttribute(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createJsxExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): JsxExpression { - let node = createNode(SyntaxKind.JsxExpression, location, flags); - node.expression = expression; - return node; - } - export function updateJsxExpression(node: JsxExpression, expression: Expression): JsxExpression { - if (expression !== node.expression) { - let newNode = createJsxExpression(expression); - return updateFrom(node, newNode); - } - return node; - } - export function createCaseClause(expression?: Expression, statements?: Array, location?: TextRange, flags?: NodeFlags): CaseClause { - let node = createNode(SyntaxKind.CaseClause, location, flags); - if (expression || statements) { - node.expression = expression; - node.statements = statements && createNodeArray(statements) - } - return node; - } - export function updateCaseClause(node: CaseClause, expression: Expression, statements: Array): CaseClause { - if (expression !== node.expression || statements !== node.statements) { - let newNode = createCaseClause(expression, statements); - return updateFrom(node, newNode); - } - return node; - } - export function createDefaultClause(statements?: Array, location?: TextRange, flags?: NodeFlags): DefaultClause { - let node = createNode(SyntaxKind.DefaultClause, location, flags); - node.statements = statements && createNodeArray(statements) - return node; - } - export function updateDefaultClause(node: DefaultClause, statements: Array): DefaultClause { - if (statements !== node.statements) { - let newNode = createDefaultClause(statements); - return updateFrom(node, newNode); - } - return node; - } - export function createHeritageClause(token?: SyntaxKind, types?: Array, - location?: TextRange, flags?: NodeFlags): HeritageClause { - let node = createNode(SyntaxKind.HeritageClause, location, flags); - if (token || types) { - 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(node.token, types); - return updateFrom(node, newNode); - } - return node; - } - export function createCatchClause(variableDeclaration?: VariableDeclaration, block?: Block, - location?: TextRange, flags?: NodeFlags): CatchClause { - let node = createNode(SyntaxKind.CatchClause, location, flags); - if (variableDeclaration || block) { - node.variableDeclaration = variableDeclaration; - node.block = block; - } - return node; - } - export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block): CatchClause { - if (variableDeclaration !== node.variableDeclaration || block !== node.block) { - let newNode = createCatchClause(variableDeclaration, block); - return updateFrom(node, newNode); - } - return node; - } - export function createPropertyAssignment(name?: PropertyName, initializer?: Expression, - location?: TextRange, flags?: NodeFlags): PropertyAssignment { - let node = createNode(SyntaxKind.PropertyAssignment, location, flags); - if (name || initializer) { - node.name = name; - 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, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createShorthandPropertyAssignment(name?: Identifier, location?: TextRange, flags?: NodeFlags): ShorthandPropertyAssignment { - let node = createNode(SyntaxKind.ShorthandPropertyAssignment, location, flags); - node.name = name; - return node; - } - export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier): ShorthandPropertyAssignment { - if (name !== node.name) { - let newNode = createShorthandPropertyAssignment(name); - return updateFrom(node, newNode); - } - return node; - } - export function createEnumMember(name?: DeclarationName, initializer?: Expression, location?: TextRange, flags?: NodeFlags): EnumMember { - let node = createNode(SyntaxKind.EnumMember, location, flags); - if (name || initializer) { - node.name = name; - node.initializer = initializer; - } - return node; - } - export function updateEnumMember(node: EnumMember, name: DeclarationName, initializer: Expression): EnumMember { - if (name !== node.name || initializer !== node.initializer) { - let newNode = createEnumMember(name, initializer); - return updateFrom(node, newNode); - } - return node; - } - export function createSourceFileNode(statements?: Array, endOfFileToken?: Node, location?: TextRange, flags?: NodeFlags): SourceFile { - let node = createNode(SyntaxKind.SourceFile, location, flags); - if (statements || endOfFileToken) { - node.statements = statements && createNodeArray(statements) - node.endOfFileToken = endOfFileToken; - } - return node; - } - export function updateSourceFileNode(node: SourceFile, statements: Array, endOfFileToken: Node): SourceFile { - if (statements !== node.statements || endOfFileToken !== node.endOfFileToken) { - let newNode = createSourceFileNode(statements, endOfFileToken); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTypeExpression(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocTypeExpression { - let node = createNode(SyntaxKind.JSDocTypeExpression, location, flags); - node.type = type; - return node; - } - export function updateJSDocTypeExpression(node: JSDocTypeExpression, type: JSDocType): JSDocTypeExpression { - if (type !== node.type) { - let newNode = createJSDocTypeExpression(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocAllType(location?: TextRange, flags?: NodeFlags): JSDocAllType { - return createNode(SyntaxKind.JSDocAllType, location, flags); - } - export function createJSDocUnknownType(location?: TextRange, flags?: NodeFlags): JSDocUnknownType { - return createNode(SyntaxKind.JSDocUnknownType, location, flags); - } - export function createJSDocArrayType(elementType?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocArrayType { - let node = createNode(SyntaxKind.JSDocArrayType, location, flags); - node.elementType = elementType; - return node; - } - export function updateJSDocArrayType(node: JSDocArrayType, elementType: JSDocType): JSDocArrayType { - if (elementType !== node.elementType) { - let newNode = createJSDocArrayType(elementType); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocUnionType { - let node = createNode(SyntaxKind.JSDocUnionType, location, flags); - node.types = types && createNodeArray(types) - return node; - } - export function updateJSDocUnionType(node: JSDocUnionType, types: Array): JSDocUnionType { - if (types !== node.types) { - let newNode = createJSDocUnionType(types); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTupleType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocTupleType { - let node = createNode(SyntaxKind.JSDocTupleType, location, flags); - node.types = types && createNodeArray(types) - return node; - } - export function updateJSDocTupleType(node: JSDocTupleType, types: Array): JSDocTupleType { - if (types !== node.types) { - let newNode = createJSDocTupleType(types); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNullableType { - let node = createNode(SyntaxKind.JSDocNullableType, location, flags); - node.type = type; - return node; - } - export function updateJSDocNullableType(node: JSDocNullableType, type: JSDocType): JSDocNullableType { - if (type !== node.type) { - let newNode = createJSDocNullableType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocNonNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNonNullableType { - let node = createNode(SyntaxKind.JSDocNonNullableType, location, flags); - node.type = type; - return node; - } - export function updateJSDocNonNullableType(node: JSDocNonNullableType, type: JSDocType): JSDocNonNullableType { - if (type !== node.type) { - let newNode = createJSDocNonNullableType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocRecordType(members?: Array, location?: TextRange, flags?: NodeFlags): JSDocRecordType { - let node = createNode(SyntaxKind.JSDocRecordType, location, flags); - node.members = members && createNodeArray(members) - return node; - } - export function updateJSDocRecordType(node: JSDocRecordType, members: Array): JSDocRecordType { - if (members !== node.members) { - let newNode = createJSDocRecordType(members); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocRecordMember(name?: Identifier | LiteralExpression, type?: JSDocType, - location?: TextRange, flags?: NodeFlags): JSDocRecordMember { - let node = createNode(SyntaxKind.JSDocRecordMember, location, flags); - if (name || type) { - node.name = name; - node.type = type; - } - return node; - } - export function updateJSDocRecordMember(node: JSDocRecordMember, name: Identifier | LiteralExpression, type: JSDocType): JSDocRecordMember { - if (name !== node.name || type !== node.type) { - let newNode = createJSDocRecordMember(name, type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTypeReference(name?: EntityName, typeArguments?: Array, - location?: TextRange, flags?: NodeFlags): JSDocTypeReference { - let node = createNode(SyntaxKind.JSDocTypeReference, location, flags); - if (name || typeArguments) { - node.name = name; - node.typeArguments = typeArguments && createNodeArray(typeArguments) - } - return node; - } - export function updateJSDocTypeReference(node: JSDocTypeReference, name: EntityName, typeArguments: Array): JSDocTypeReference { - if (name !== node.name || typeArguments !== node.typeArguments) { - let newNode = createJSDocTypeReference(name, typeArguments); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocOptionalType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocOptionalType { - let node = createNode(SyntaxKind.JSDocOptionalType, location, flags); - node.type = type; - return node; - } - export function updateJSDocOptionalType(node: JSDocOptionalType, type: JSDocType): JSDocOptionalType { - if (type !== node.type) { - let newNode = createJSDocOptionalType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocFunctionType(parameters?: Array, type?: JSDocType, - location?: TextRange, flags?: NodeFlags): JSDocFunctionType { - let node = createNode(SyntaxKind.JSDocFunctionType, location, flags); - if (parameters || type) { - node.parameters = parameters && createNodeArray(parameters) - node.type = type; - } - return node; - } - export function updateJSDocFunctionType(node: JSDocFunctionType, parameters: Array, type: JSDocType): JSDocFunctionType { - if (parameters !== node.parameters || type !== node.type) { - let newNode = createJSDocFunctionType(parameters, type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocVariadicType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocVariadicType { - let node = createNode(SyntaxKind.JSDocVariadicType, location, flags); - node.type = type; - return node; - } - export function updateJSDocVariadicType(node: JSDocVariadicType, type: JSDocType): JSDocVariadicType { - if (type !== node.type) { - let newNode = createJSDocVariadicType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocConstructorType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocConstructorType { - let node = createNode(SyntaxKind.JSDocConstructorType, location, flags); - node.type = type; - return node; - } - export function updateJSDocConstructorType(node: JSDocConstructorType, type: JSDocType): JSDocConstructorType { - if (type !== node.type) { - let newNode = createJSDocConstructorType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocThisType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocThisType { - let node = createNode(SyntaxKind.JSDocThisType, location, flags); - node.type = type; - return node; - } - export function updateJSDocThisType(node: JSDocThisType, type: JSDocType): JSDocThisType { - if (type !== node.type) { - let newNode = createJSDocThisType(type); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocComment(tags?: Array, location?: TextRange, flags?: NodeFlags): JSDocComment { - let node = createNode(SyntaxKind.JSDocComment, location, flags); - node.tags = tags && createNodeArray(tags) - return node; - } - export function updateJSDocComment(node: JSDocComment, tags: Array): JSDocComment { - if (tags !== node.tags) { - let newNode = createJSDocComment(tags); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTag(atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTag { - let node = createNode(SyntaxKind.JSDocTag, location, flags); - if (atToken || tagName) { - node.atToken = atToken; - node.tagName = tagName; - } - return node; - } - export function updateJSDocTag(node: JSDocTag, tagName: Identifier): JSDocTag { - if (tagName !== node.tagName) { - let newNode = createJSDocTag(node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocParameterTag(preParameterName?: Identifier, typeExpression?: JSDocTypeExpression, postParameterName?: Identifier, - atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocParameterTag { - let node = createNode(SyntaxKind.JSDocParameterTag, location, flags); - if (preParameterName || typeExpression || postParameterName || atToken || tagName) { - node.preParameterName = preParameterName; - node.typeExpression = typeExpression; - node.postParameterName = postParameterName; - node.atToken = atToken; - node.tagName = tagName; - } - return node; - } - export function updateJSDocParameterTag(node: JSDocParameterTag, preParameterName: Identifier, typeExpression: JSDocTypeExpression - , postParameterName: Identifier, tagName: Identifier): JSDocParameterTag { - if (preParameterName !== node.preParameterName || typeExpression !== node.typeExpression || postParameterName !== node.postParameterName || - tagName !== node.tagName) { - let newNode = createJSDocParameterTag(preParameterName, typeExpression, postParameterName, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, - location?: TextRange, flags?: NodeFlags): JSDocReturnTag { - let node = createNode(SyntaxKind.JSDocReturnTag, location, flags); - if (typeExpression || atToken || tagName) { - node.typeExpression = typeExpression; - node.atToken = atToken; - node.tagName = tagName; - } - return node; - } - export function updateJSDocReturnTag(node: JSDocReturnTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocReturnTag { - if (typeExpression !== node.typeExpression || tagName !== node.tagName) { - let newNode = createJSDocReturnTag(typeExpression, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTypeTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, - location?: TextRange, flags?: NodeFlags): JSDocTypeTag { - let node = createNode(SyntaxKind.JSDocTypeTag, location, flags); - if (typeExpression || atToken || tagName) { - node.typeExpression = typeExpression; - node.atToken = atToken; - node.tagName = tagName; - } - return node; - } - export function updateJSDocTypeTag(node: JSDocTypeTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocTypeTag { - if (typeExpression !== node.typeExpression || tagName !== node.tagName) { - let newNode = createJSDocTypeTag(typeExpression, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function createJSDocTemplateTag(typeParameters?: Array, atToken?: Node, tagName?: Identifier, - location?: TextRange, flags?: NodeFlags): JSDocTemplateTag { - let node = createNode(SyntaxKind.JSDocTemplateTag, location, flags); - if (typeParameters || atToken || tagName) { - node.typeParameters = typeParameters && createNodeArray(typeParameters) - node.atToken = atToken; - node.tagName = tagName; - } - return node; - } - export function updateJSDocTemplateTag(node: JSDocTemplateTag, typeParameters: Array, tagName: Identifier - ): JSDocTemplateTag { - if (typeParameters !== node.typeParameters || tagName !== node.tagName) { - let newNode = createJSDocTemplateTag(typeParameters, node.atToken, tagName); - return updateFrom(node, newNode); - } - return node; - } - export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode; - export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node { - if (!node) { - return node; - } - switch (node.kind) { - case SyntaxKind.NumericLiteral: - return createNumericLiteral((node).text, location, flags); - case SyntaxKind.StringLiteral: - return createStringLiteral((node).text, location, flags); - case SyntaxKind.RegularExpressionLiteral: - return createRegularExpressionLiteral((node).text, location, flags); - case SyntaxKind.NoSubstitutionTemplateLiteral: - return createNoSubstitutionTemplateLiteral((node).text, location, flags); - case SyntaxKind.TemplateHead: - return createTemplateHead((node).text, location, flags); - case SyntaxKind.TemplateMiddle: - return createTemplateMiddle((node).text, location, flags); - case SyntaxKind.TemplateTail: - return createTemplateTail((node).text, location, flags); - case SyntaxKind.Identifier: - return createIdentifier((node).text, (node).originalKeywordKind, location, flags); - case SyntaxKind.FalseKeyword: - return createFalseKeyword(location, flags); - case SyntaxKind.SuperKeyword: - return createSuperKeyword(location, flags); - case SyntaxKind.ThisKeyword: - return createThisKeyword(location, flags); - case SyntaxKind.TrueKeyword: - return createTrueKeyword(location, flags); - case SyntaxKind.QualifiedName: - return createQualifiedName((node).left, (node).right, location, flags); - case SyntaxKind.ComputedPropertyName: - return createComputedPropertyName((node).expression, location, flags); - case SyntaxKind.TypeParameter: - return createTypeParameter((node).name, (node).constraint, - (node).expression, location, flags); - case SyntaxKind.Parameter: - return createParameter((node).decorators, (node).modifiers, - (node).dotDotDotToken, (node).name, (node).questionToken, - (node).type, (node).initializer, location, flags); - case SyntaxKind.Decorator: - return createDecorator((node).expression, location, flags); - case SyntaxKind.PropertySignature: - return createPropertySignature((node).decorators, (node).modifiers, - (node).name, (node).questionToken, (node).type, location, flags); - case SyntaxKind.PropertyDeclaration: - return createPropertyDeclaration((node).decorators, (node).modifiers, - (node).name, (node).type, (node).initializer, location, flags); - case SyntaxKind.MethodSignature: - return createMethodSignature((node).decorators, (node).modifiers, (node).name, - (node).questionToken, (node).typeParameters, (node).parameters, - (node).type, location, flags); - case SyntaxKind.MethodDeclaration: - return createMethodDeclaration((node).decorators, (node).modifiers, - (node).asteriskToken, (node).name, (node).typeParameters, - (node).parameters, (node).type, (node).body, location, flags); - case SyntaxKind.Constructor: - return createConstructor((node).decorators, (node).modifiers, - (node).parameters, (node).type, (node).body, - location, flags); - case SyntaxKind.GetAccessor: - return createGetAccessor((node).decorators, (node).modifiers, - (node).name, (node).parameters, (node).type, - (node).body, location, flags); - case SyntaxKind.SetAccessor: - return createSetAccessor((node).decorators, (node).modifiers, - (node).name, (node).parameters, (node).type, - (node).body, location, flags); - case SyntaxKind.CallSignature: - return createCallSignature((node).typeParameters, (node).parameters, - (node).type, (node).questionToken, location, flags); - case SyntaxKind.ConstructSignature: - return createConstructSignature((node).typeParameters, - (node).parameters, (node).type, - (node).questionToken, location, flags); - case SyntaxKind.IndexSignature: - return createIndexSignature((node).decorators, (node).modifiers, - (node).parameters, (node).type, - (node).questionToken, location, flags); - case SyntaxKind.TypePredicate: - return createTypePredicate((node).parameterName, (node).type, location, flags); - case SyntaxKind.TypeReference: - return createTypeReference((node).typeName, (node).typeArguments, location, flags); - case SyntaxKind.FunctionType: - return createFunctionType((node).typeParameters, (node).parameters, - (node).type, location, flags); - case SyntaxKind.ConstructorType: - return createConstructorType((node).typeParameters, (node).parameters, - (node).type, location, flags); - case SyntaxKind.TypeQuery: - return createTypeQuery((node).exprName, location, flags); - case SyntaxKind.TypeLiteral: - return createTypeLiteral((node).members, location, flags); - case SyntaxKind.ArrayType: - return createArrayType((node).elementType, location, flags); - case SyntaxKind.TupleType: - return createTupleType((node).elementTypes, location, flags); - case SyntaxKind.UnionType: - return createUnionType((node).types, location, flags); - case SyntaxKind.IntersectionType: - return createIntersectionType((node).types, location, flags); - case SyntaxKind.ParenthesizedType: - return createParenthesizedType((node).type, location, flags); - case SyntaxKind.ObjectBindingPattern: - return createObjectBindingPattern((node).elements, location, flags); - case SyntaxKind.ArrayBindingPattern: - return createArrayBindingPattern((node).elements, location, flags); - case SyntaxKind.BindingElement: - return createBindingElement((node).decorators, (node).modifiers, (node).propertyName, - (node).dotDotDotToken, (node).name, (node).initializer, location, flags); - case SyntaxKind.ArrayLiteralExpression: - return createArrayLiteralExpression((node).elements, location, flags); - case SyntaxKind.ObjectLiteralExpression: - return createObjectLiteralExpression((node).decorators, (node).modifiers, - (node).properties, location, flags); - case SyntaxKind.PropertyAccessExpression: - return createPropertyAccessExpression((node).expression, (node).dotToken, - (node).name, location, flags); - case SyntaxKind.ElementAccessExpression: - return createElementAccessExpression((node).expression, (node).argumentExpression, - location, flags); - case SyntaxKind.CallExpression: - return createCallExpression((node).expression, (node).typeArguments, - (node).arguments, location, flags); - case SyntaxKind.NewExpression: - return createNewExpression((node).expression, (node).typeArguments, (node).arguments, - location, flags); - case SyntaxKind.TaggedTemplateExpression: - return createTaggedTemplateExpression((node).tag, (node).template, - location, flags); - case SyntaxKind.TypeAssertionExpression: - return createTypeAssertionExpression((node).type, (node).expression, location, flags); - case SyntaxKind.ParenthesizedExpression: - return createParenthesizedExpression((node).expression, location, flags); - case SyntaxKind.FunctionExpression: - return createFunctionExpression((node).decorators, (node).modifiers, - (node).asteriskToken, (node).name, (node).typeParameters, - (node).parameters, (node).type, (node).body, location, flags); - case SyntaxKind.ArrowFunction: - return createArrowFunction((node).decorators, (node).modifiers, (node).typeParameters, - (node).parameters, (node).type, (node).equalsGreaterThanToken, - (node).body, location, flags); - case SyntaxKind.DeleteExpression: - return createDeleteExpression((node).expression, location, flags); - case SyntaxKind.TypeOfExpression: - return createTypeOfExpression((node).expression, location, flags); - case SyntaxKind.VoidExpression: - return createVoidExpression((node).expression, location, flags); - case SyntaxKind.AwaitExpression: - return createAwaitExpression((node).expression, location, flags); - case SyntaxKind.PrefixUnaryExpression: - return createPrefixUnaryExpression((node).operator, (node).operand, location, flags); - case SyntaxKind.PostfixUnaryExpression: - return createPostfixUnaryExpression((node).operand, (node).operator, - location, flags); - case SyntaxKind.BinaryExpression: - return createBinaryExpression((node).left, (node).operatorToken, (node).right, - location, flags); - case SyntaxKind.ConditionalExpression: - return createConditionalExpression((node).condition, (node).questionToken, - (node).whenTrue, (node).colonToken, (node).whenFalse, - location, flags); - case SyntaxKind.TemplateExpression: - return createTemplateExpression((node).head, (node).templateSpans, location, flags); - case SyntaxKind.YieldExpression: - return createYieldExpression((node).asteriskToken, (node).expression, location, flags); - case SyntaxKind.SpreadElementExpression: - return createSpreadElementExpression((node).expression, location, flags); - case SyntaxKind.ClassExpression: - return createClassExpression((node).decorators, (node).modifiers, (node).name, - (node).typeParameters, (node).heritageClauses, (node).members, - location, flags); - case SyntaxKind.OmittedExpression: - return createOmittedExpression(location, flags); - case SyntaxKind.ExpressionWithTypeArguments: - return createExpressionWithTypeArguments((node).expression, - (node).typeArguments, location, flags); - case SyntaxKind.AsExpression: - return createAsExpression((node).expression, (node).type, location, flags); - case SyntaxKind.TemplateSpan: - return createTemplateSpan((node).expression, (node).literal, location, flags); - case SyntaxKind.SemicolonClassElement: - return createSemicolonClassElement(location, flags); - case SyntaxKind.Block: - return createBlock((node).statements, location, flags); - case SyntaxKind.VariableStatement: - return createVariableStatement((node).decorators, (node).modifiers, - (node).declarationList, location, flags); - case SyntaxKind.EmptyStatement: - return createEmptyStatement(location, flags); - case SyntaxKind.ExpressionStatement: - return createExpressionStatement((node).expression, location, flags); - case SyntaxKind.IfStatement: - return createIfStatement((node).expression, (node).thenStatement, (node).elseStatement, - location, flags); - case SyntaxKind.DoStatement: - return createDoStatement((node).statement, (node).expression, location, flags); - case SyntaxKind.WhileStatement: - return createWhileStatement((node).expression, (node).statement, location, flags); - case SyntaxKind.ForStatement: - return createForStatement((node).initializer, (node).condition, (node).incrementor, - (node).statement, location, flags); - case SyntaxKind.ForInStatement: - return createForInStatement((node).initializer, (node).expression, (node).statement, - location, flags); - case SyntaxKind.ForOfStatement: - return createForOfStatement((node).initializer, (node).expression, (node).statement, - location, flags); - case SyntaxKind.ContinueStatement: - return createContinueStatement((node).label, location, flags); - case SyntaxKind.BreakStatement: - return createBreakStatement((node).label, location, flags); - case SyntaxKind.ReturnStatement: - return createReturnStatement((node).expression, location, flags); - case SyntaxKind.WithStatement: - return createWithStatement((node).expression, (node).statement, location, flags); - case SyntaxKind.SwitchStatement: - return createSwitchStatement((node).expression, (node).caseBlock, location, flags); - case SyntaxKind.LabeledStatement: - return createLabeledStatement((node).label, (node).statement, location, flags); - case SyntaxKind.ThrowStatement: - return createThrowStatement((node).expression, location, flags); - case SyntaxKind.TryStatement: - return createTryStatement((node).tryBlock, (node).catchClause, (node).finallyBlock, - location, flags); - case SyntaxKind.DebuggerStatement: - return createDebuggerStatement(location, flags); - case SyntaxKind.VariableDeclaration: - return createVariableDeclaration((node).name, (node).type, - (node).initializer, location, flags); - case SyntaxKind.VariableDeclarationList: - return createVariableDeclarationList((node).declarations, location, flags); - case SyntaxKind.FunctionDeclaration: - return createFunctionDeclaration((node).decorators, (node).modifiers, - (node).asteriskToken, (node).name, (node).typeParameters, - (node).parameters, (node).type, (node).body, location, flags); - case SyntaxKind.ClassDeclaration: - return createClassDeclaration((node).decorators, (node).modifiers, (node).name, - (node).typeParameters, (node).heritageClauses, (node).members, - location, flags); - case SyntaxKind.InterfaceDeclaration: - return createInterfaceDeclaration((node).decorators, (node).modifiers, - (node).name, (node).typeParameters, (node).heritageClauses, - (node).members, location, flags); - case SyntaxKind.TypeAliasDeclaration: - return createTypeAliasDeclaration((node).decorators, (node).modifiers, - (node).name, (node).typeParameters, (node).type, - location, flags); - case SyntaxKind.EnumDeclaration: - return createEnumDeclaration((node).decorators, (node).modifiers, (node).name, - (node).members, location, flags); - case SyntaxKind.ModuleDeclaration: - return createModuleDeclaration((node).decorators, (node).modifiers, - (node).name, (node).body, location, flags); - case SyntaxKind.ModuleBlock: - return createModuleBlock((node).statements, location, flags); - case SyntaxKind.CaseBlock: - return createCaseBlock((node).clauses, location, flags); - case SyntaxKind.ImportEqualsDeclaration: - return createImportEqualsDeclaration((node).decorators, (node).modifiers, - (node).name, (node).moduleReference, location, flags); - case SyntaxKind.ImportDeclaration: - return createImportDeclaration((node).decorators, (node).modifiers, - (node).importClause, (node).moduleSpecifier, location, flags); - case SyntaxKind.ImportClause: - return createImportClause((node).name, (node).namedBindings, location, flags); - case SyntaxKind.NamespaceImport: - return createNamespaceImport((node).name, location, flags); - case SyntaxKind.NamedImports: - return createNamedImports((node).elements, location, flags); - case SyntaxKind.ImportSpecifier: - return createImportSpecifier((node).propertyName, (node).name, location, flags); - case SyntaxKind.ExportAssignment: - return createExportAssignment((node).decorators, (node).modifiers, - (node).expression, location, flags); - case SyntaxKind.ExportDeclaration: - return createExportDeclaration((node).decorators, (node).modifiers, - (node).exportClause, (node).moduleSpecifier, location, flags); - case SyntaxKind.NamedExports: - return createNamedExports((node).elements, location, flags); - case SyntaxKind.ExportSpecifier: - return createExportSpecifier((node).propertyName, (node).name, location, flags); - case SyntaxKind.MissingDeclaration: - return createMissingDeclaration((node).decorators, (node).modifiers, - (node).questionToken, location, flags); - case SyntaxKind.ExternalModuleReference: - return createExternalModuleReference((node).expression, location, flags); - case SyntaxKind.JsxElement: - return createJsxElement((node).openingElement, (node).children, (node).closingElement, - location, flags); - case SyntaxKind.JsxSelfClosingElement: - return createJsxSelfClosingElement((node).tagName, (node).attributes, location, flags); - case SyntaxKind.JsxOpeningElement: - return createJsxOpeningElement((node).tagName, (node).attributes, location, flags); - case SyntaxKind.JsxText: - return createJsxText(location, flags); - case SyntaxKind.JsxClosingElement: - return createJsxClosingElement((node).tagName, location, flags); - case SyntaxKind.JsxAttribute: - return createJsxAttribute((node).name, (node).initializer, location, flags); - case SyntaxKind.JsxSpreadAttribute: - return createJsxSpreadAttribute((node).expression, location, flags); - case SyntaxKind.JsxExpression: - return createJsxExpression((node).expression, location, flags); - case SyntaxKind.CaseClause: - return createCaseClause((node).expression, (node).statements, location, flags); - case SyntaxKind.DefaultClause: - return createDefaultClause((node).statements, location, flags); - case SyntaxKind.HeritageClause: - return createHeritageClause((node).token, (node).types, location, flags); - case SyntaxKind.CatchClause: - return createCatchClause((node).variableDeclaration, (node).block, location, flags); - case SyntaxKind.PropertyAssignment: - return createPropertyAssignment((node).name, (node).initializer, location, flags); - case SyntaxKind.ShorthandPropertyAssignment: - return createShorthandPropertyAssignment((node).name, location, flags); - case SyntaxKind.EnumMember: - return createEnumMember((node).name, (node).initializer, location, flags); - case SyntaxKind.SourceFile: - return createSourceFileNode((node).statements, (node).endOfFileToken, location, flags); - case SyntaxKind.JSDocTypeExpression: - return createJSDocTypeExpression((node).type, location, flags); - case SyntaxKind.JSDocAllType: - return createJSDocAllType(location, flags); - case SyntaxKind.JSDocUnknownType: - return createJSDocUnknownType(location, flags); - case SyntaxKind.JSDocArrayType: - return createJSDocArrayType((node).elementType, location, flags); - case SyntaxKind.JSDocUnionType: - return createJSDocUnionType((node).types, location, flags); - case SyntaxKind.JSDocTupleType: - return createJSDocTupleType((node).types, location, flags); - case SyntaxKind.JSDocNullableType: - return createJSDocNullableType((node).type, location, flags); - case SyntaxKind.JSDocNonNullableType: - return createJSDocNonNullableType((node).type, location, flags); - case SyntaxKind.JSDocRecordType: - return createJSDocRecordType((node).members, location, flags); - case SyntaxKind.JSDocRecordMember: - return createJSDocRecordMember((node).name, (node).type, location, flags); - case SyntaxKind.JSDocTypeReference: - return createJSDocTypeReference((node).name, (node).typeArguments, location, flags); - case SyntaxKind.JSDocOptionalType: - return createJSDocOptionalType((node).type, location, flags); - case SyntaxKind.JSDocFunctionType: - return createJSDocFunctionType((node).parameters, (node).type, location, flags); - case SyntaxKind.JSDocVariadicType: - return createJSDocVariadicType((node).type, location, flags); - case SyntaxKind.JSDocConstructorType: - return createJSDocConstructorType((node).type, location, flags); - case SyntaxKind.JSDocThisType: - return createJSDocThisType((node).type, location, flags); - case SyntaxKind.JSDocComment: - return createJSDocComment((node).tags, location, flags); - case SyntaxKind.JSDocTag: - return createJSDocTag((node).atToken, (node).tagName, location, flags); - case SyntaxKind.JSDocParameterTag: - return createJSDocParameterTag((node).preParameterName, (node).typeExpression, - (node).postParameterName, (node).atToken, (node).tagName, - location, flags); - case SyntaxKind.JSDocReturnTag: - return createJSDocReturnTag((node).typeExpression, (node).atToken, (node).tagName, - location, flags); - case SyntaxKind.JSDocTypeTag: - return createJSDocTypeTag((node).typeExpression, (node).atToken, (node).tagName, - location, flags); - case SyntaxKind.JSDocTemplateTag: - return createJSDocTemplateTag((node).typeParameters, (node).atToken, - (node).tagName, location, flags); - } - } - export function isNumericLiteral(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.NumericLiteral; - } - export function isStringLiteral(node: Node): node is StringLiteral { - return node && node.kind === SyntaxKind.StringLiteral; - } - export function isRegularExpressionLiteral(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.RegularExpressionLiteral; - } - export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; - } - export function isTemplateHead(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateHead; - } - export function isTemplateMiddle(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateMiddle; - } - export function isTemplateTail(node: Node): node is LiteralExpression { - return node && node.kind === SyntaxKind.TemplateTail; - } - export function isIdentifier(node: Node): node is Identifier { - return node && node.kind === SyntaxKind.Identifier; - } - export function isFalseKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.FalseKeyword; - } - export function isNullKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.NullKeyword; - } - export function isSuperKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.SuperKeyword; - } - export function isThisKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.ThisKeyword; - } - export function isTrueKeyword(node: Node): node is PrimaryExpression { - return node && node.kind === SyntaxKind.TrueKeyword; - } - export function isQualifiedName(node: Node): node is QualifiedName { - return node && node.kind === SyntaxKind.QualifiedName; - } - export function isComputedPropertyName(node: Node): node is ComputedPropertyName { - return node && node.kind === SyntaxKind.ComputedPropertyName; - } - export function isTypeParameter(node: Node): node is TypeParameterDeclaration { - return node && node.kind === SyntaxKind.TypeParameter; - } - export function isParameter(node: Node): node is ParameterDeclaration { - return node && node.kind === SyntaxKind.Parameter; - } - export function isDecorator(node: Node): node is Decorator { - return node && node.kind === SyntaxKind.Decorator; - } - export function isPropertySignature(node: Node): node is PropertySignature { - return node && node.kind === SyntaxKind.PropertySignature; - } - export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { - return node && node.kind === SyntaxKind.PropertyDeclaration; - } - export function isMethodSignature(node: Node): node is MethodSignature { - return node && node.kind === SyntaxKind.MethodSignature; - } - export function isMethodDeclaration(node: Node): node is MethodDeclaration { - return node && node.kind === SyntaxKind.MethodDeclaration; - } - export function isConstructor(node: Node): node is ConstructorDeclaration { - return node && node.kind === SyntaxKind.Constructor; - } - export function isGetAccessor(node: Node): node is GetAccessorDeclaration { - return node && node.kind === SyntaxKind.GetAccessor; - } - export function isSetAccessor(node: Node): node is SetAccessorDeclaration { - return node && node.kind === SyntaxKind.SetAccessor; - } - export function isCallSignature(node: Node): node is CallSignatureDeclaration { - return node && node.kind === SyntaxKind.CallSignature; - } - export function isConstructSignature(node: Node): node is ConstructSignatureDeclaration { - return node && node.kind === SyntaxKind.ConstructSignature; - } - export function isIndexSignature(node: Node): node is IndexSignatureDeclaration { - return node && node.kind === SyntaxKind.IndexSignature; - } - export function isTypePredicate(node: Node): node is TypePredicateNode { - return node && node.kind === SyntaxKind.TypePredicate; - } - export function isTypeReference(node: Node): node is TypeReferenceNode { - return node && node.kind === SyntaxKind.TypeReference; - } - export function isFunctionType(node: Node): node is FunctionTypeNode { - return node && node.kind === SyntaxKind.FunctionType; - } - export function isConstructorType(node: Node): node is ConstructorTypeNode { - return node && node.kind === SyntaxKind.ConstructorType; - } - export function isTypeQuery(node: Node): node is TypeQueryNode { - return node && node.kind === SyntaxKind.TypeQuery; - } - export function isTypeLiteral(node: Node): node is TypeLiteralNode { - return node && node.kind === SyntaxKind.TypeLiteral; - } - export function isArrayType(node: Node): node is ArrayTypeNode { - return node && node.kind === SyntaxKind.ArrayType; - } - export function isTupleType(node: Node): node is TupleTypeNode { - return node && node.kind === SyntaxKind.TupleType; - } - export function isUnionType(node: Node): node is UnionTypeNode { - return node && node.kind === SyntaxKind.UnionType; - } - export function isIntersectionType(node: Node): node is IntersectionTypeNode { - return node && node.kind === SyntaxKind.IntersectionType; - } - export function isParenthesizedType(node: Node): node is ParenthesizedTypeNode { - return node && node.kind === SyntaxKind.ParenthesizedType; - } - export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { - return node && node.kind === SyntaxKind.ObjectBindingPattern; - } - export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { - return node && node.kind === SyntaxKind.ArrayBindingPattern; - } - export function isBindingElement(node: Node): node is BindingElement { - return node && node.kind === SyntaxKind.BindingElement; - } - export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { - return node && node.kind === SyntaxKind.ArrayLiteralExpression; - } - export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { - return node && node.kind === SyntaxKind.ObjectLiteralExpression; - } - export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { - return node && node.kind === SyntaxKind.PropertyAccessExpression; - } - export function isElementAccessExpression(node: Node): node is ElementAccessExpression { - return node && node.kind === SyntaxKind.ElementAccessExpression; - } - export function isCallExpression(node: Node): node is CallExpression { - return node && node.kind === SyntaxKind.CallExpression; - } - export function isNewExpression(node: Node): node is NewExpression { - return node && node.kind === SyntaxKind.NewExpression; - } - export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { - return node && node.kind === SyntaxKind.TaggedTemplateExpression; - } - export function isTypeAssertionExpression(node: Node): node is TypeAssertion { - return node && node.kind === SyntaxKind.TypeAssertionExpression; - } - export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { - return node && node.kind === SyntaxKind.ParenthesizedExpression; - } - export function isFunctionExpression(node: Node): node is FunctionExpression { - return node && node.kind === SyntaxKind.FunctionExpression; - } - export function isArrowFunction(node: Node): node is ArrowFunction { - return node && node.kind === SyntaxKind.ArrowFunction; - } - export function isDeleteExpression(node: Node): node is DeleteExpression { - return node && node.kind === SyntaxKind.DeleteExpression; - } - export function isTypeOfExpression(node: Node): node is TypeOfExpression { - return node && node.kind === SyntaxKind.TypeOfExpression; - } - export function isVoidExpression(node: Node): node is VoidExpression { - return node && node.kind === SyntaxKind.VoidExpression; - } - export function isAwaitExpression(node: Node): node is AwaitExpression { - return node && node.kind === SyntaxKind.AwaitExpression; - } - export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { - return node && node.kind === SyntaxKind.PrefixUnaryExpression; - } - export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { - return node && node.kind === SyntaxKind.PostfixUnaryExpression; - } - export function isBinaryExpression(node: Node): node is BinaryExpression { - return node && node.kind === SyntaxKind.BinaryExpression; - } - export function isConditionalExpression(node: Node): node is ConditionalExpression { - return node && node.kind === SyntaxKind.ConditionalExpression; - } - export function isTemplateExpression(node: Node): node is TemplateExpression { - return node && node.kind === SyntaxKind.TemplateExpression; - } - export function isYieldExpression(node: Node): node is YieldExpression { - return node && node.kind === SyntaxKind.YieldExpression; - } - export function isSpreadElementExpression(node: Node): node is SpreadElementExpression { - return node && node.kind === SyntaxKind.SpreadElementExpression; - } - export function isClassExpression(node: Node): node is ClassExpression { - return node && node.kind === SyntaxKind.ClassExpression; - } - export function isOmittedExpression(node: Node): node is Expression { - return node && node.kind === SyntaxKind.OmittedExpression; - } - export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { - return node && node.kind === SyntaxKind.ExpressionWithTypeArguments; - } - export function isAsExpression(node: Node): node is AsExpression { - return node && node.kind === SyntaxKind.AsExpression; - } - export function isTemplateSpan(node: Node): node is TemplateSpan { - return node && node.kind === SyntaxKind.TemplateSpan; - } - export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { - return node && node.kind === SyntaxKind.SemicolonClassElement; - } - export function isBlock(node: Node): node is Block { - return node && node.kind === SyntaxKind.Block; - } - export function isVariableStatement(node: Node): node is VariableStatement { - return node && node.kind === SyntaxKind.VariableStatement; - } - export function isEmptyStatement(node: Node): node is EmptyStatement { - return node && node.kind === SyntaxKind.EmptyStatement; - } - export function isExpressionStatement(node: Node): node is ExpressionStatement { - return node && node.kind === SyntaxKind.ExpressionStatement; - } - export function isIfStatement(node: Node): node is IfStatement { - return node && node.kind === SyntaxKind.IfStatement; - } - export function isDoStatement(node: Node): node is DoStatement { - return node && node.kind === SyntaxKind.DoStatement; - } - export function isWhileStatement(node: Node): node is WhileStatement { - return node && node.kind === SyntaxKind.WhileStatement; - } - export function isForStatement(node: Node): node is ForStatement { - return node && node.kind === SyntaxKind.ForStatement; - } - export function isForInStatement(node: Node): node is ForInStatement { - return node && node.kind === SyntaxKind.ForInStatement; - } - export function isForOfStatement(node: Node): node is ForOfStatement { - return node && node.kind === SyntaxKind.ForOfStatement; - } - export function isContinueStatement(node: Node): node is ContinueStatement { - return node && node.kind === SyntaxKind.ContinueStatement; - } - export function isBreakStatement(node: Node): node is BreakStatement { - return node && node.kind === SyntaxKind.BreakStatement; - } - export function isReturnStatement(node: Node): node is ReturnStatement { - return node && node.kind === SyntaxKind.ReturnStatement; - } - export function isWithStatement(node: Node): node is WithStatement { - return node && node.kind === SyntaxKind.WithStatement; - } - export function isSwitchStatement(node: Node): node is SwitchStatement { - return node && node.kind === SyntaxKind.SwitchStatement; - } - export function isLabeledStatement(node: Node): node is LabeledStatement { - return node && node.kind === SyntaxKind.LabeledStatement; - } - export function isThrowStatement(node: Node): node is ThrowStatement { - return node && node.kind === SyntaxKind.ThrowStatement; - } - export function isTryStatement(node: Node): node is TryStatement { - return node && node.kind === SyntaxKind.TryStatement; - } - export function isDebuggerStatement(node: Node): node is DebuggerStatement { - return node && node.kind === SyntaxKind.DebuggerStatement; - } - export function isVariableDeclaration(node: Node): node is VariableDeclaration { - return node && node.kind === SyntaxKind.VariableDeclaration; - } - export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { - return node && node.kind === SyntaxKind.VariableDeclarationList; - } - export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { - return node && node.kind === SyntaxKind.FunctionDeclaration; - } - export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node && node.kind === SyntaxKind.ClassDeclaration; - } - export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { - return node && node.kind === SyntaxKind.InterfaceDeclaration; - } - export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { - return node && node.kind === SyntaxKind.TypeAliasDeclaration; - } - export function isEnumDeclaration(node: Node): node is EnumDeclaration { - return node && node.kind === SyntaxKind.EnumDeclaration; - } - export function isModuleDeclaration(node: Node): node is ModuleDeclaration { - return node && node.kind === SyntaxKind.ModuleDeclaration; - } - export function isModuleBlock(node: Node): node is ModuleBlock { - return node && node.kind === SyntaxKind.ModuleBlock; - } - export function isCaseBlock(node: Node): node is CaseBlock { - return node && node.kind === SyntaxKind.CaseBlock; - } - export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { - return node && node.kind === SyntaxKind.ImportEqualsDeclaration; - } - export function isImportDeclaration(node: Node): node is ImportDeclaration { - return node && node.kind === SyntaxKind.ImportDeclaration; - } - export function isImportClause(node: Node): node is ImportClause { - return node && node.kind === SyntaxKind.ImportClause; - } - export function isNamespaceImport(node: Node): node is NamespaceImport { - return node && node.kind === SyntaxKind.NamespaceImport; - } - export function isNamedImports(node: Node): node is NamedImports { - return node && node.kind === SyntaxKind.NamedImports; - } - export function isImportSpecifier(node: Node): node is ImportSpecifier { - return node && node.kind === SyntaxKind.ImportSpecifier; - } - export function isExportAssignment(node: Node): node is ExportAssignment { - return node && node.kind === SyntaxKind.ExportAssignment; - } - export function isExportDeclaration(node: Node): node is ExportDeclaration { - return node && node.kind === SyntaxKind.ExportDeclaration; - } - export function isNamedExports(node: Node): node is NamedExports { - return node && node.kind === SyntaxKind.NamedExports; - } - export function isExportSpecifier(node: Node): node is ExportSpecifier { - return node && node.kind === SyntaxKind.ExportSpecifier; - } - export function isMissingDeclaration(node: Node): node is MissingDeclaration { - return node && node.kind === SyntaxKind.MissingDeclaration; - } - export function isExternalModuleReference(node: Node): node is ExternalModuleReference { - return node && node.kind === SyntaxKind.ExternalModuleReference; - } - export function isJsxElement(node: Node): node is JsxElement { - return node && node.kind === SyntaxKind.JsxElement; - } - export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { - return node && node.kind === SyntaxKind.JsxSelfClosingElement; - } - export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { - return node && node.kind === SyntaxKind.JsxOpeningElement; - } - export function isJsxText(node: Node): node is JsxText { - return node && node.kind === SyntaxKind.JsxText; - } - export function isJsxClosingElement(node: Node): node is JsxClosingElement { - return node && node.kind === SyntaxKind.JsxClosingElement; - } - export function isJsxAttribute(node: Node): node is JsxAttribute { - return node && node.kind === SyntaxKind.JsxAttribute; - } - export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { - return node && node.kind === SyntaxKind.JsxSpreadAttribute; - } - export function isJsxExpression(node: Node): node is JsxExpression { - return node && node.kind === SyntaxKind.JsxExpression; - } - export function isCaseClause(node: Node): node is CaseClause { - return node && node.kind === SyntaxKind.CaseClause; - } - export function isDefaultClause(node: Node): node is DefaultClause { - return node && node.kind === SyntaxKind.DefaultClause; - } - export function isHeritageClause(node: Node): node is HeritageClause { - return node && node.kind === SyntaxKind.HeritageClause; - } - export function isCatchClause(node: Node): node is CatchClause { - return node && node.kind === SyntaxKind.CatchClause; - } - export function isPropertyAssignment(node: Node): node is PropertyAssignment { - return node && node.kind === SyntaxKind.PropertyAssignment; - } - export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { - return node && node.kind === SyntaxKind.ShorthandPropertyAssignment; - } - export function isEnumMember(node: Node): node is EnumMember { - return node && node.kind === SyntaxKind.EnumMember; - } - export function isSourceFile(node: Node): node is SourceFile { - return node && node.kind === SyntaxKind.SourceFile; - } - export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { - return node && node.kind === SyntaxKind.JSDocTypeExpression; - } - export function isJSDocAllType(node: Node): node is JSDocAllType { - return node && node.kind === SyntaxKind.JSDocAllType; - } - export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { - return node && node.kind === SyntaxKind.JSDocUnknownType; - } - export function isJSDocArrayType(node: Node): node is JSDocArrayType { - return node && node.kind === SyntaxKind.JSDocArrayType; - } - export function isJSDocUnionType(node: Node): node is JSDocUnionType { - return node && node.kind === SyntaxKind.JSDocUnionType; - } - export function isJSDocTupleType(node: Node): node is JSDocTupleType { - return node && node.kind === SyntaxKind.JSDocTupleType; - } - export function isJSDocNullableType(node: Node): node is JSDocNullableType { - return node && node.kind === SyntaxKind.JSDocNullableType; - } - export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { - return node && node.kind === SyntaxKind.JSDocNonNullableType; - } - export function isJSDocRecordType(node: Node): node is JSDocRecordType { - return node && node.kind === SyntaxKind.JSDocRecordType; - } - export function isJSDocRecordMember(node: Node): node is JSDocRecordMember { - return node && node.kind === SyntaxKind.JSDocRecordMember; - } - export function isJSDocTypeReference(node: Node): node is JSDocTypeReference { - return node && node.kind === SyntaxKind.JSDocTypeReference; - } - export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { - return node && node.kind === SyntaxKind.JSDocOptionalType; - } - export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { - return node && node.kind === SyntaxKind.JSDocFunctionType; - } - export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { - return node && node.kind === SyntaxKind.JSDocVariadicType; - } - export function isJSDocConstructorType(node: Node): node is JSDocConstructorType { - return node && node.kind === SyntaxKind.JSDocConstructorType; - } - export function isJSDocThisType(node: Node): node is JSDocThisType { - return node && node.kind === SyntaxKind.JSDocThisType; - } - export function isJSDocComment(node: Node): node is JSDocComment { - return node && node.kind === SyntaxKind.JSDocComment; - } - export function isJSDocTag(node: Node): node is JSDocTag { - return node && node.kind === SyntaxKind.JSDocTag; - } - export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { - return node && node.kind === SyntaxKind.JSDocParameterTag; - } - export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { - return node && node.kind === SyntaxKind.JSDocReturnTag; - } - export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { - return node && node.kind === SyntaxKind.JSDocTypeTag; - } - export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { - return node && node.kind === SyntaxKind.JSDocTemplateTag; - } - export function isEntityName(node: Node): node is EntityName { - if (node) { - switch (node.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: - return true; - } - } - return false; - } - export function isExpressionNode(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) { - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.Identifier: - return true; - } - } - return false; - } - export function isModifier(node: Node): node is Modifier { - if (node) { - switch (node.kind) { - case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.ConstKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.DefaultKeyword: - case SyntaxKind.ExportKeyword: - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.StaticKeyword: - return true; - } - } - return false; - } - export function isPropertyName(node: Node): node is PropertyName { - if (node) { - switch (node.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.NumericLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - case SyntaxKind.StringLiteral: - case SyntaxKind.ComputedPropertyName: - return true; - } - } - return false; - } - export function isTypeElement(node: Node): node is TypeElement { - if (node) { - switch (node.kind) { - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.MissingDeclaration: - case SyntaxKind.JSDocRecordMember: - return true; - } - } - return false; - } - export function isUnaryExpression(node: Node): node is UnaryExpression { - if (node) { - switch (node.kind) { - 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.FunctionExpression: - case SyntaxKind.TemplateExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.ClassExpression: - return true; - } - } - return false; - } - export function isBlockOrExpression(node: Node): node is Block | Expression { - if (node) { - switch (node.kind) { - case SyntaxKind.Block: - 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 isLiteralExpression(node: Node): node is LiteralExpression { - if (node) { - switch (node.kind) { - case SyntaxKind.NumericLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - case SyntaxKind.StringLiteral: - return true; - } - } - return false; - } - export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { - if (node) { - switch (node.kind) { - case SyntaxKind.PropertyAssignment: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.MissingDeclaration: - return true; - } - } - return false; - } - export function isLiteralExpressionOrTemplateExpression(node: Node): node is LiteralExpression | TemplateExpression { - if (node) { - switch (node.kind) { - case SyntaxKind.NumericLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - case SyntaxKind.StringLiteral: - case SyntaxKind.TemplateExpression: - return true; - } - } - return false; - } - export function isJsxChild(node: Node): node is JsxChild { - if (node) { - switch (node.kind) { - case SyntaxKind.JsxText: - case SyntaxKind.JsxExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - return true; - } - } - return false; - } - export function isJsxAttributeOrJsxSpreadAttribute(node: Node): node is JsxAttribute | JsxSpreadAttribute { - if (node) { - switch (node.kind) { - case SyntaxKind.JsxAttribute: - case SyntaxKind.JsxSpreadAttribute: - return true; - } - } - return false; - } - export function isStatementNode(node: Node): node is Statement { - if (node) { - switch (node.kind) { - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.Block: - case SyntaxKind.EmptyStatement: - case SyntaxKind.DebuggerStatement: - case SyntaxKind.MissingDeclaration: - case SyntaxKind.VariableStatement: - case SyntaxKind.ExpressionStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.WithStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.LabeledStatement: - case SyntaxKind.ThrowStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ModuleBlock: - case SyntaxKind.ImportEqualsDeclaration: - case SyntaxKind.ImportDeclaration: - case SyntaxKind.ExportDeclaration: - case SyntaxKind.ExportAssignment: - return true; - } - } - return false; - } - export function isExpressionOrVariableDeclarationList(node: Node): node is Expression | VariableDeclarationList { - 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: - case SyntaxKind.VariableDeclarationList: - return true; - } - } - return false; - } - export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { - if (node) { - switch (node.kind) { - case SyntaxKind.CaseClause: - case SyntaxKind.DefaultClause: - return true; - } - } - return false; - } - export function isClassElement(node: Node): node is ClassElement { - if (node) { - switch (node.kind) { - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.Constructor: - case SyntaxKind.SemicolonClassElement: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.IndexSignature: - case SyntaxKind.MissingDeclaration: - return true; - } - } - return false; - } - export function isIdentifierOrLiteralExpression(node: Node): node is Identifier | LiteralExpression { - if (node) { - switch (node.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.NumericLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - case SyntaxKind.StringLiteral: - return true; - } - } - return false; - } - export function isModuleBlockOrModuleDeclaration(node: Node): node is ModuleBlock | ModuleDeclaration { - if (node) { - switch (node.kind) { - case SyntaxKind.ModuleBlock: - case SyntaxKind.ModuleDeclaration: - return true; - } - } - return false; - } - export function isEntityNameOrExternalModuleReference(node: Node): node is EntityName | ExternalModuleReference { - if (node) { - switch (node.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: - case SyntaxKind.ExternalModuleReference: - return true; - } - } - return false; - } - export function isNamedImportsOrNamespaceImport(node: Node): node is NamedImports | NamespaceImport { - if (node) { - switch (node.kind) { - case SyntaxKind.NamedImports: - case SyntaxKind.NamespaceImport: - return true; - } - } - return false; - } - export function isImportOrExportSpecifier(node: Node): node is ImportOrExportSpecifier { - if (node) { - switch (node.kind) { - case SyntaxKind.ImportSpecifier: - case SyntaxKind.ExportSpecifier: - return true; - } - } - return false; - } - export function isJSDocType(node: Node): node is JSDocType { - if (node) { - switch (node.kind) { - case SyntaxKind.JSDocAllType: - case SyntaxKind.JSDocUnknownType: - case SyntaxKind.JSDocArrayType: - case SyntaxKind.JSDocUnionType: - case SyntaxKind.JSDocTupleType: - case SyntaxKind.JSDocNonNullableType: - case SyntaxKind.JSDocNullableType: - case SyntaxKind.JSDocRecordType: - case SyntaxKind.JSDocTypeReference: - case SyntaxKind.JSDocOptionalType: - case SyntaxKind.JSDocFunctionType: - case SyntaxKind.JSDocVariadicType: - case SyntaxKind.JSDocConstructorType: - case SyntaxKind.JSDocThisType: - return true; - } - } - return false; - } -} + +// +/// +namespace ts { + export function createNumericLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.NumericLiteral, location, flags); + if (text) node.text = text; + return node; + } + export function createStringLiteral(text?: string, location?: TextRange, flags?: NodeFlags): StringLiteral { + let node = createNode(SyntaxKind.StringLiteral, location, flags); + if (text) node.text = text; + return node; + } + export function createRegularExpressionLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.RegularExpressionLiteral, location, flags); + if (text) node.text = text; + return node; + } + export function createNoSubstitutionTemplateLiteral(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.NoSubstitutionTemplateLiteral, location, flags); + if (text) node.text = text; + return node; + } + export function createTemplateHead(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.TemplateHead, location, flags); + if (text) node.text = text; + return node; + } + export function createTemplateMiddle(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.TemplateMiddle, location, flags); + if (text) node.text = text; + return node; + } + export function createTemplateTail(text?: string, location?: TextRange, flags?: NodeFlags): LiteralExpression { + let node = createNode(SyntaxKind.TemplateTail, location, flags); + if (text) node.text = text; + return node; + } + export function createIdentifier(text?: string, originalKeywordKind?: SyntaxKind, location?: TextRange, flags?: NodeFlags): Identifier { + let node = createNode(SyntaxKind.Identifier, location, flags); + if (text) node.text = text; + if (originalKeywordKind) node.originalKeywordKind = originalKeywordKind; + return node; + } + export function createFalseKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + let node = createNode(SyntaxKind.FalseKeyword, location, flags); + return node; + } + export function createNullKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + let node = createNode(SyntaxKind.NullKeyword, location, flags); + return node; + } + export function createSuperKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + let node = createNode(SyntaxKind.SuperKeyword, location, flags); + return node; + } + export function createThisKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + let node = createNode(SyntaxKind.ThisKeyword, location, flags); + return node; + } + export function createTrueKeyword(location?: TextRange, flags?: NodeFlags): PrimaryExpression { + let node = createNode(SyntaxKind.TrueKeyword, location, flags); + return node; + } + export function createQualifiedName(left?: EntityName, right?: Identifier, location?: TextRange, flags?: NodeFlags): QualifiedName { + let node = createNode(SyntaxKind.QualifiedName, location, flags); + if (left) node.left = left; + if (right) node.right = right; + return node; + } + export function createComputedPropertyName(expression?: Expression, location?: TextRange, flags?: NodeFlags): ComputedPropertyName { + let node = createNode(SyntaxKind.ComputedPropertyName, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createTypeParameter(name?: Identifier, constraint?: TypeNode, expression?: Expression, location?: TextRange, flags?: NodeFlags): TypeParameterDeclaration { + let node = createNode(SyntaxKind.TypeParameter, location, flags); + if (name) node.name = name; + if (constraint) node.constraint = constraint; + if (expression) node.expression = expression; + return node; + } + export function createParameter(decorators?: Array, modifiers?: Array, dotDotDotToken?: Node, name?: BindingPattern | Identifier, questionToken?: Node, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): ParameterDeclaration { + let node = createNode(SyntaxKind.Parameter, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (dotDotDotToken) node.dotDotDotToken = dotDotDotToken; + if (name) node.name = name; + if (questionToken) node.questionToken = questionToken; + if (type) node.type = type; + if (initializer) node.initializer = initializer; + return node; + } + export function createDecorator(expression?: LeftHandSideExpression, location?: TextRange, flags?: NodeFlags): Decorator { + let node = createNode(SyntaxKind.Decorator, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createPropertySignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, type?: TypeNode, location?: TextRange, flags?: NodeFlags): PropertySignature { + let node = createNode(SyntaxKind.PropertySignature, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (questionToken) node.questionToken = questionToken; + if (type) node.type = type; + return node; + } + export function createPropertyDeclaration(decorators?: Array, modifiers?: Array, name?: PropertyName, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyDeclaration { + let node = createNode(SyntaxKind.PropertyDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (type) node.type = type; + if (initializer) node.initializer = initializer; + return node; + } + export function createMethodSignature(decorators?: Array, modifiers?: Array, name?: PropertyName, questionToken?: Node, typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): MethodSignature { + let node = createNode(SyntaxKind.MethodSignature, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (questionToken) node.questionToken = questionToken; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + return node; + } + export function createMethodDeclaration(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: PropertyName, typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): MethodDeclaration { + let node = createNode(SyntaxKind.MethodDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (asteriskToken) node.asteriskToken = asteriskToken; + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createConstructor(decorators?: Array, modifiers?: Array, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration { + let node = createNode(SyntaxKind.Constructor, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createGetAccessor(decorators?: Array, modifiers?: Array, name?: PropertyName, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration { + let node = createNode(SyntaxKind.GetAccessor, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createSetAccessor(decorators?: Array, modifiers?: Array, name?: PropertyName, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration { + let node = createNode(SyntaxKind.SetAccessor, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createCallSignature(typeParameters?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): CallSignatureDeclaration { + let node = createNode(SyntaxKind.CallSignature, location, flags); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (questionToken) node.questionToken = questionToken; + return node; + } + export function createConstructSignature(typeParameters?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): ConstructSignatureDeclaration { + let node = createNode(SyntaxKind.ConstructSignature, location, flags); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (questionToken) node.questionToken = questionToken; + return node; + } + export function createIndexSignature(decorators?: Array, modifiers?: Array, parameters?: Array, type?: TypeNode, questionToken?: Node, location?: TextRange, flags?: NodeFlags): IndexSignatureDeclaration { + let node = createNode(SyntaxKind.IndexSignature, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (questionToken) node.questionToken = questionToken; + return node; + } + export function createTypePredicate(parameterName?: Identifier, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypePredicateNode { + let node = createNode(SyntaxKind.TypePredicate, location, flags); + if (parameterName) node.parameterName = parameterName; + if (type) node.type = type; + return node; + } + export function createTypeReference(typeName?: EntityName, typeArguments?: Array, location?: TextRange, flags?: NodeFlags): TypeReferenceNode { + let node = createNode(SyntaxKind.TypeReference, location, flags); + if (typeName) node.typeName = typeName; + if (typeArguments) node.typeArguments = createNodeArray(typeArguments); + return node; + } + export function createFunctionType(typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): FunctionTypeNode { + let node = createNode(SyntaxKind.FunctionType, location, flags); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + return node; + } + export function createConstructorType(typeParameters?: Array, parameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): ConstructorTypeNode { + let node = createNode(SyntaxKind.ConstructorType, location, flags); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + return node; + } + export function createTypeQuery(exprName?: EntityName, location?: TextRange, flags?: NodeFlags): TypeQueryNode { + let node = createNode(SyntaxKind.TypeQuery, location, flags); + if (exprName) node.exprName = exprName; + return node; + } + export function createTypeLiteral(members?: Array, location?: TextRange, flags?: NodeFlags): TypeLiteralNode { + let node = createNode(SyntaxKind.TypeLiteral, location, flags); + if (members) node.members = createNodeArray(members); + return node; + } + export function createArrayType(elementType?: TypeNode, location?: TextRange, flags?: NodeFlags): ArrayTypeNode { + let node = createNode(SyntaxKind.ArrayType, location, flags); + if (elementType) node.elementType = elementType; + return node; + } + export function createTupleType(elementTypes?: Array, location?: TextRange, flags?: NodeFlags): TupleTypeNode { + let node = createNode(SyntaxKind.TupleType, location, flags); + if (elementTypes) node.elementTypes = createNodeArray(elementTypes); + return node; + } + export function createUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): UnionTypeNode { + let node = createNode(SyntaxKind.UnionType, location, flags); + if (types) node.types = createNodeArray(types); + return node; + } + export function createIntersectionType(types?: Array, location?: TextRange, flags?: NodeFlags): IntersectionTypeNode { + let node = createNode(SyntaxKind.IntersectionType, location, flags); + if (types) node.types = createNodeArray(types); + return node; + } + export function createParenthesizedType(type?: TypeNode, location?: TextRange, flags?: NodeFlags): ParenthesizedTypeNode { + let node = createNode(SyntaxKind.ParenthesizedType, location, flags); + if (type) node.type = type; + return node; + } + export function createObjectBindingPattern(elements?: Array, location?: TextRange, flags?: NodeFlags): ObjectBindingPattern { + let node = createNode(SyntaxKind.ObjectBindingPattern, location, flags); + if (elements) node.elements = createNodeArray(elements); + return node; + } + export function createArrayBindingPattern(elements?: Array, location?: TextRange, flags?: NodeFlags): ArrayBindingPattern { + let node = createNode(SyntaxKind.ArrayBindingPattern, location, flags); + if (elements) node.elements = createNodeArray(elements); + return node; + } + export function createBindingElement(propertyName?: Identifier, dotDotDotToken?: Node, name?: BindingPattern | Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags): BindingElement { + let node = createNode(SyntaxKind.BindingElement, location, flags); + if (propertyName) node.propertyName = propertyName; + if (dotDotDotToken) node.dotDotDotToken = dotDotDotToken; + if (name) node.name = name; + if (initializer) node.initializer = initializer; + return node; + } + export function createArrayLiteralExpression(elements?: Array, location?: TextRange, flags?: NodeFlags): ArrayLiteralExpression { + let node = createNode(SyntaxKind.ArrayLiteralExpression, location, flags); + if (elements) node.elements = createNodeArray(elements); + return node; + } + export function createObjectLiteralExpression(properties?: Array, location?: TextRange, flags?: NodeFlags): ObjectLiteralExpression { + let node = createNode(SyntaxKind.ObjectLiteralExpression, location, flags); + if (properties) node.properties = createNodeArray(properties); + return node; + } + export function createPropertyAccessExpression(expression?: LeftHandSideExpression, dotToken?: Node, name?: Identifier, location?: TextRange, flags?: NodeFlags): PropertyAccessExpression { + let node = createNode(SyntaxKind.PropertyAccessExpression, location, flags); + if (expression) node.expression = expression; + if (dotToken) node.dotToken = dotToken; + if (name) node.name = name; + return node; + } + export function createElementAccessExpression(expression?: LeftHandSideExpression, argumentExpression?: Expression, location?: TextRange, flags?: NodeFlags): ElementAccessExpression { + let node = createNode(SyntaxKind.ElementAccessExpression, location, flags); + if (expression) node.expression = expression; + if (argumentExpression) node.argumentExpression = argumentExpression; + return node; + } + export function createCallExpression(expression?: LeftHandSideExpression, typeArguments?: Array, _arguments?: Array, location?: TextRange, flags?: NodeFlags): CallExpression { + let node = createNode(SyntaxKind.CallExpression, location, flags); + if (expression) node.expression = expression; + if (typeArguments) node.typeArguments = createNodeArray(typeArguments); + if (_arguments) node.arguments = createNodeArray(_arguments); + return node; + } + export function createNewExpression(expression?: LeftHandSideExpression, typeArguments?: Array, _arguments?: Array, location?: TextRange, flags?: NodeFlags): NewExpression { + let node = createNode(SyntaxKind.NewExpression, location, flags); + if (expression) node.expression = expression; + if (typeArguments) node.typeArguments = createNodeArray(typeArguments); + if (_arguments) node.arguments = createNodeArray(_arguments); + return node; + } + export function createTaggedTemplateExpression(tag?: LeftHandSideExpression, template?: LiteralExpression | TemplateExpression, location?: TextRange, flags?: NodeFlags): TaggedTemplateExpression { + let node = createNode(SyntaxKind.TaggedTemplateExpression, location, flags); + if (tag) node.tag = tag; + if (template) node.template = template; + return node; + } + export function createTypeAssertionExpression(type?: TypeNode, expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): TypeAssertion { + let node = createNode(SyntaxKind.TypeAssertionExpression, location, flags); + if (type) node.type = type; + if (expression) node.expression = expression; + return node; + } + export function createParenthesizedExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): ParenthesizedExpression { + let node = createNode(SyntaxKind.ParenthesizedExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createFunctionExpression(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: Identifier, typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): FunctionExpression { + let node = createNode(SyntaxKind.FunctionExpression, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (asteriskToken) node.asteriskToken = asteriskToken; + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createArrowFunction(decorators?: Array, modifiers?: Array, typeParameters?: Array, parameters?: Array, type?: TypeNode, equalsGreaterThanToken?: Node, body?: ConciseBody, location?: TextRange, flags?: NodeFlags): ArrowFunction { + let node = createNode(SyntaxKind.ArrowFunction, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (equalsGreaterThanToken) node.equalsGreaterThanToken = equalsGreaterThanToken; + if (body) node.body = body; + return node; + } + export function createDeleteExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): DeleteExpression { + let node = createNode(SyntaxKind.DeleteExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createTypeOfExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): TypeOfExpression { + let node = createNode(SyntaxKind.TypeOfExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createVoidExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): VoidExpression { + let node = createNode(SyntaxKind.VoidExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createAwaitExpression(expression?: UnaryExpression, location?: TextRange, flags?: NodeFlags): AwaitExpression { + let node = createNode(SyntaxKind.AwaitExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createPrefixUnaryExpression(operator?: SyntaxKind, operand?: UnaryExpression, location?: TextRange, flags?: NodeFlags): PrefixUnaryExpression { + let node = createNode(SyntaxKind.PrefixUnaryExpression, location, flags); + if (operator) node.operator = operator; + if (operand) node.operand = operand; + return node; + } + export function createPostfixUnaryExpression(operand?: LeftHandSideExpression, operator?: SyntaxKind, location?: TextRange, flags?: NodeFlags): PostfixUnaryExpression { + let node = createNode(SyntaxKind.PostfixUnaryExpression, location, flags); + if (operand) node.operand = operand; + if (operator) node.operator = operator; + return node; + } + export function createBinaryExpression(left?: Expression, operatorToken?: Node, right?: Expression, location?: TextRange, flags?: NodeFlags): BinaryExpression { + let node = createNode(SyntaxKind.BinaryExpression, location, flags); + if (left) node.left = left; + if (operatorToken) node.operatorToken = operatorToken; + if (right) node.right = right; + return node; + } + export function createConditionalExpression(condition?: Expression, questionToken?: Node, whenTrue?: Expression, colonToken?: Node, whenFalse?: Expression, location?: TextRange, flags?: NodeFlags): ConditionalExpression { + let node = createNode(SyntaxKind.ConditionalExpression, location, flags); + if (condition) node.condition = condition; + if (questionToken) node.questionToken = questionToken; + if (whenTrue) node.whenTrue = whenTrue; + if (colonToken) node.colonToken = colonToken; + if (whenFalse) node.whenFalse = whenFalse; + return node; + } + export function createTemplateExpression(head?: LiteralExpression, templateSpans?: Array, location?: TextRange, flags?: NodeFlags): TemplateExpression { + let node = createNode(SyntaxKind.TemplateExpression, location, flags); + if (head) node.head = head; + if (templateSpans) node.templateSpans = createNodeArray(templateSpans); + return node; + } + export function createYieldExpression(asteriskToken?: Node, expression?: Expression, location?: TextRange, flags?: NodeFlags): YieldExpression { + let node = createNode(SyntaxKind.YieldExpression, location, flags); + if (asteriskToken) node.asteriskToken = asteriskToken; + if (expression) node.expression = expression; + return node; + } + export function createSpreadElementExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): SpreadElementExpression { + let node = createNode(SyntaxKind.SpreadElementExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createClassExpression(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, heritageClauses?: Array, members?: Array, location?: TextRange, flags?: NodeFlags): ClassExpression { + let node = createNode(SyntaxKind.ClassExpression, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (heritageClauses) node.heritageClauses = createNodeArray(heritageClauses); + if (members) node.members = createNodeArray(members); + return node; + } + export function createOmittedExpression(location?: TextRange, flags?: NodeFlags): OmittedExpression { + let node = createNode(SyntaxKind.OmittedExpression, location, flags); + return node; + } + export function createExpressionWithTypeArguments(expression?: LeftHandSideExpression, typeArguments?: Array, location?: TextRange, flags?: NodeFlags): ExpressionWithTypeArguments { + let node = createNode(SyntaxKind.ExpressionWithTypeArguments, location, flags); + if (expression) node.expression = expression; + if (typeArguments) node.typeArguments = createNodeArray(typeArguments); + return node; + } + export function createAsExpression(expression?: Expression, type?: TypeNode, location?: TextRange, flags?: NodeFlags): AsExpression { + let node = createNode(SyntaxKind.AsExpression, location, flags); + if (expression) node.expression = expression; + if (type) node.type = type; + return node; + } + export function createTemplateSpan(expression?: Expression, literal?: LiteralExpression, location?: TextRange, flags?: NodeFlags): TemplateSpan { + let node = createNode(SyntaxKind.TemplateSpan, location, flags); + if (expression) node.expression = expression; + if (literal) node.literal = literal; + return node; + } + export function createSemicolonClassElement(location?: TextRange, flags?: NodeFlags): SemicolonClassElement { + let node = createNode(SyntaxKind.SemicolonClassElement, location, flags); + return node; + } + export function createBlock(statements?: Array, location?: TextRange, flags?: NodeFlags): Block { + let node = createNode(SyntaxKind.Block, location, flags); + if (statements) node.statements = createNodeArray(statements); + return node; + } + export function createVariableStatement(decorators?: Array, modifiers?: Array, declarationList?: VariableDeclarationList, location?: TextRange, flags?: NodeFlags): VariableStatement { + let node = createNode(SyntaxKind.VariableStatement, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (declarationList) node.declarationList = declarationList; + return node; + } + export function createEmptyStatement(location?: TextRange, flags?: NodeFlags): EmptyStatement { + let node = createNode(SyntaxKind.EmptyStatement, location, flags); + return node; + } + export function createExpressionStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ExpressionStatement { + let node = createNode(SyntaxKind.ExpressionStatement, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createIfStatement(expression?: Expression, thenStatement?: Statement, elseStatement?: Statement, location?: TextRange, flags?: NodeFlags): IfStatement { + let node = createNode(SyntaxKind.IfStatement, location, flags); + if (expression) node.expression = expression; + if (thenStatement) node.thenStatement = thenStatement; + if (elseStatement) node.elseStatement = elseStatement; + return node; + } + export function createDoStatement(statement?: Statement, expression?: Expression, location?: TextRange, flags?: NodeFlags): DoStatement { + let node = createNode(SyntaxKind.DoStatement, location, flags); + if (statement) node.statement = statement; + if (expression) node.expression = expression; + return node; + } + export function createWhileStatement(expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): WhileStatement { + let node = createNode(SyntaxKind.WhileStatement, location, flags); + if (expression) node.expression = expression; + if (statement) node.statement = statement; + return node; + } + export function createForStatement(initializer?: Expression | VariableDeclarationList, condition?: Expression, incrementor?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): ForStatement { + let node = createNode(SyntaxKind.ForStatement, location, flags); + if (initializer) node.initializer = initializer; + if (condition) node.condition = condition; + if (incrementor) node.incrementor = incrementor; + if (statement) node.statement = statement; + return node; + } + export function createForInStatement(initializer?: Expression | VariableDeclarationList, expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): ForInStatement { + let node = createNode(SyntaxKind.ForInStatement, location, flags); + if (initializer) node.initializer = initializer; + if (expression) node.expression = expression; + if (statement) node.statement = statement; + return node; + } + export function createForOfStatement(initializer?: Expression | VariableDeclarationList, expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): ForOfStatement { + let node = createNode(SyntaxKind.ForOfStatement, location, flags); + if (initializer) node.initializer = initializer; + if (expression) node.expression = expression; + if (statement) node.statement = statement; + return node; + } + export function createContinueStatement(label?: Identifier, location?: TextRange, flags?: NodeFlags): ContinueStatement { + let node = createNode(SyntaxKind.ContinueStatement, location, flags); + if (label) node.label = label; + return node; + } + export function createBreakStatement(label?: Identifier, location?: TextRange, flags?: NodeFlags): BreakStatement { + let node = createNode(SyntaxKind.BreakStatement, location, flags); + if (label) node.label = label; + return node; + } + export function createReturnStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ReturnStatement { + let node = createNode(SyntaxKind.ReturnStatement, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createWithStatement(expression?: Expression, statement?: Statement, location?: TextRange, flags?: NodeFlags): WithStatement { + let node = createNode(SyntaxKind.WithStatement, location, flags); + if (expression) node.expression = expression; + if (statement) node.statement = statement; + return node; + } + export function createSwitchStatement(expression?: Expression, caseBlock?: CaseBlock, location?: TextRange, flags?: NodeFlags): SwitchStatement { + let node = createNode(SyntaxKind.SwitchStatement, location, flags); + if (expression) node.expression = expression; + if (caseBlock) node.caseBlock = caseBlock; + return node; + } + export function createLabeledStatement(label?: Identifier, statement?: Statement, location?: TextRange, flags?: NodeFlags): LabeledStatement { + let node = createNode(SyntaxKind.LabeledStatement, location, flags); + if (label) node.label = label; + if (statement) node.statement = statement; + return node; + } + export function createThrowStatement(expression?: Expression, location?: TextRange, flags?: NodeFlags): ThrowStatement { + let node = createNode(SyntaxKind.ThrowStatement, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createTryStatement(tryBlock?: Block, catchClause?: CatchClause, finallyBlock?: Block, location?: TextRange, flags?: NodeFlags): TryStatement { + let node = createNode(SyntaxKind.TryStatement, location, flags); + if (tryBlock) node.tryBlock = tryBlock; + if (catchClause) node.catchClause = catchClause; + if (finallyBlock) node.finallyBlock = finallyBlock; + return node; + } + export function createDebuggerStatement(location?: TextRange, flags?: NodeFlags): DebuggerStatement { + let node = createNode(SyntaxKind.DebuggerStatement, location, flags); + return node; + } + export function createVariableDeclaration(name?: BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): VariableDeclaration { + let node = createNode(SyntaxKind.VariableDeclaration, location, flags); + if (name) node.name = name; + if (type) node.type = type; + if (initializer) node.initializer = initializer; + return node; + } + export function createVariableDeclarationList(declarations?: Array, location?: TextRange, flags?: NodeFlags): VariableDeclarationList { + let node = createNode(SyntaxKind.VariableDeclarationList, location, flags); + if (declarations) node.declarations = createNodeArray(declarations); + return node; + } + export function createFunctionDeclaration(decorators?: Array, modifiers?: Array, asteriskToken?: Node, name?: Identifier, typeParameters?: Array, parameters?: Array, type?: TypeNode, body?: FunctionBody, location?: TextRange, flags?: NodeFlags): FunctionDeclaration { + let node = createNode(SyntaxKind.FunctionDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (asteriskToken) node.asteriskToken = asteriskToken; + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + if (body) node.body = body; + return node; + } + export function createClassDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, heritageClauses?: Array, members?: Array, location?: TextRange, flags?: NodeFlags): ClassDeclaration { + let node = createNode(SyntaxKind.ClassDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (heritageClauses) node.heritageClauses = createNodeArray(heritageClauses); + if (members) node.members = createNodeArray(members); + return node; + } + export function createInterfaceDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, heritageClauses?: Array, members?: Array, location?: TextRange, flags?: NodeFlags): InterfaceDeclaration { + let node = createNode(SyntaxKind.InterfaceDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (heritageClauses) node.heritageClauses = createNodeArray(heritageClauses); + if (members) node.members = createNodeArray(members); + return node; + } + export function createTypeAliasDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, typeParameters?: Array, type?: TypeNode, location?: TextRange, flags?: NodeFlags): TypeAliasDeclaration { + let node = createNode(SyntaxKind.TypeAliasDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (type) node.type = type; + return node; + } + export function createEnumDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, members?: Array, location?: TextRange, flags?: NodeFlags): EnumDeclaration { + let node = createNode(SyntaxKind.EnumDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (members) node.members = createNodeArray(members); + return node; + } + export function createModuleDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier | LiteralExpression, body?: ModuleBody, location?: TextRange, flags?: NodeFlags): ModuleDeclaration { + let node = createNode(SyntaxKind.ModuleDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (body) node.body = body; + return node; + } + export function createModuleBlock(statements?: Array, location?: TextRange, flags?: NodeFlags): ModuleBlock { + let node = createNode(SyntaxKind.ModuleBlock, location, flags); + if (statements) node.statements = createNodeArray(statements); + return node; + } + export function createCaseBlock(clauses?: Array, location?: TextRange, flags?: NodeFlags): CaseBlock { + let node = createNode(SyntaxKind.CaseBlock, location, flags); + if (clauses) node.clauses = createNodeArray(clauses); + return node; + } + export function createImportEqualsDeclaration(decorators?: Array, modifiers?: Array, name?: Identifier, moduleReference?: EntityName | ExternalModuleReference, location?: TextRange, flags?: NodeFlags): ImportEqualsDeclaration { + let node = createNode(SyntaxKind.ImportEqualsDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (name) node.name = name; + if (moduleReference) node.moduleReference = moduleReference; + return node; + } + export function createImportDeclaration(decorators?: Array, modifiers?: Array, importClause?: ImportClause, moduleSpecifier?: Expression, location?: TextRange, flags?: NodeFlags): ImportDeclaration { + let node = createNode(SyntaxKind.ImportDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (importClause) node.importClause = importClause; + if (moduleSpecifier) node.moduleSpecifier = moduleSpecifier; + return node; + } + export function createImportClause(name?: Identifier, namedBindings?: NamedImports | NamespaceImport, location?: TextRange, flags?: NodeFlags): ImportClause { + let node = createNode(SyntaxKind.ImportClause, location, flags); + if (name) node.name = name; + if (namedBindings) node.namedBindings = namedBindings; + return node; + } + export function createNamespaceImport(name?: Identifier, location?: TextRange, flags?: NodeFlags): NamespaceImport { + let node = createNode(SyntaxKind.NamespaceImport, location, flags); + if (name) node.name = name; + return node; + } + export function createNamedImports(elements?: Array, location?: TextRange, flags?: NodeFlags): NamedImports { + let node = createNode(SyntaxKind.NamedImports, location, flags); + if (elements) node.elements = createNodeArray(elements); + return node; + } + export function createImportSpecifier(propertyName?: Identifier, name?: Identifier, location?: TextRange, flags?: NodeFlags): ImportSpecifier { + let node = createNode(SyntaxKind.ImportSpecifier, location, flags); + if (propertyName) node.propertyName = propertyName; + if (name) node.name = name; + return node; + } + export function createExportAssignment(decorators?: Array, modifiers?: Array, expression?: Expression, location?: TextRange, flags?: NodeFlags): ExportAssignment { + let node = createNode(SyntaxKind.ExportAssignment, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (expression) node.expression = expression; + return node; + } + export function createExportDeclaration(decorators?: Array, modifiers?: Array, exportClause?: NamedExports, moduleSpecifier?: Expression, location?: TextRange, flags?: NodeFlags): ExportDeclaration { + let node = createNode(SyntaxKind.ExportDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (exportClause) node.exportClause = exportClause; + if (moduleSpecifier) node.moduleSpecifier = moduleSpecifier; + return node; + } + export function createNamedExports(elements?: Array, location?: TextRange, flags?: NodeFlags): NamedExports { + let node = createNode(SyntaxKind.NamedExports, location, flags); + if (elements) node.elements = createNodeArray(elements); + return node; + } + export function createExportSpecifier(propertyName?: Identifier, name?: Identifier, location?: TextRange, flags?: NodeFlags): ExportSpecifier { + let node = createNode(SyntaxKind.ExportSpecifier, location, flags); + if (propertyName) node.propertyName = propertyName; + if (name) node.name = name; + return node; + } + export function createMissingDeclaration(decorators?: Array, modifiers?: Array, questionToken?: Node, location?: TextRange, flags?: NodeFlags): MissingDeclaration { + let node = createNode(SyntaxKind.MissingDeclaration, location, flags); + if (decorators) node.decorators = createNodeArray(decorators); + if (modifiers) setModifiers(node, modifiers); + if (questionToken) node.questionToken = questionToken; + return node; + } + export function createExternalModuleReference(expression?: Expression, location?: TextRange, flags?: NodeFlags): ExternalModuleReference { + let node = createNode(SyntaxKind.ExternalModuleReference, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createJsxElement(openingElement?: JsxOpeningElement, children?: Array, closingElement?: JsxClosingElement, location?: TextRange, flags?: NodeFlags): JsxElement { + let node = createNode(SyntaxKind.JsxElement, location, flags); + if (openingElement) node.openingElement = openingElement; + if (children) node.children = createNodeArray(children); + if (closingElement) node.closingElement = closingElement; + return node; + } + export function createJsxSelfClosingElement(tagName?: EntityName, attributes?: Array, location?: TextRange, flags?: NodeFlags): JsxSelfClosingElement { + let node = createNode(SyntaxKind.JsxSelfClosingElement, location, flags); + if (tagName) node.tagName = tagName; + if (attributes) node.attributes = createNodeArray(attributes); + return node; + } + export function createJsxOpeningElement(tagName?: EntityName, attributes?: Array, location?: TextRange, flags?: NodeFlags): JsxOpeningElement { + let node = createNode(SyntaxKind.JsxOpeningElement, location, flags); + if (tagName) node.tagName = tagName; + if (attributes) node.attributes = createNodeArray(attributes); + return node; + } + export function createJsxText(location?: TextRange, flags?: NodeFlags): JsxText { + let node = createNode(SyntaxKind.JsxText, location, flags); + return node; + } + export function createJsxClosingElement(tagName?: EntityName, location?: TextRange, flags?: NodeFlags): JsxClosingElement { + let node = createNode(SyntaxKind.JsxClosingElement, location, flags); + if (tagName) node.tagName = tagName; + return node; + } + export function createJsxAttribute(name?: Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags): JsxAttribute { + let node = createNode(SyntaxKind.JsxAttribute, location, flags); + if (name) node.name = name; + if (initializer) node.initializer = initializer; + return node; + } + export function createJsxSpreadAttribute(expression?: Expression, location?: TextRange, flags?: NodeFlags): JsxSpreadAttribute { + let node = createNode(SyntaxKind.JsxSpreadAttribute, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createJsxExpression(expression?: Expression, location?: TextRange, flags?: NodeFlags): JsxExpression { + let node = createNode(SyntaxKind.JsxExpression, location, flags); + if (expression) node.expression = expression; + return node; + } + export function createCaseClause(expression?: Expression, statements?: Array, location?: TextRange, flags?: NodeFlags): CaseClause { + let node = createNode(SyntaxKind.CaseClause, location, flags); + if (expression) node.expression = expression; + if (statements) node.statements = createNodeArray(statements); + return node; + } + export function createDefaultClause(statements?: Array, location?: TextRange, flags?: NodeFlags): DefaultClause { + let node = createNode(SyntaxKind.DefaultClause, location, flags); + if (statements) node.statements = createNodeArray(statements); + return node; + } + export function createHeritageClause(token?: SyntaxKind, types?: Array, location?: TextRange, flags?: NodeFlags): HeritageClause { + let node = createNode(SyntaxKind.HeritageClause, location, flags); + if (token) node.token = token; + if (types) node.types = createNodeArray(types); + return node; + } + export function createCatchClause(variableDeclaration?: VariableDeclaration, block?: Block, location?: TextRange, flags?: NodeFlags): CatchClause { + let node = createNode(SyntaxKind.CatchClause, location, flags); + if (variableDeclaration) node.variableDeclaration = variableDeclaration; + if (block) node.block = block; + return node; + } + export function createPropertyAssignment(name?: PropertyName, initializer?: Expression, location?: TextRange, flags?: NodeFlags): PropertyAssignment { + let node = createNode(SyntaxKind.PropertyAssignment, location, flags); + if (name) node.name = name; + if (initializer) node.initializer = initializer; + return node; + } + export function createShorthandPropertyAssignment(name?: Identifier, location?: TextRange, flags?: NodeFlags): ShorthandPropertyAssignment { + let node = createNode(SyntaxKind.ShorthandPropertyAssignment, location, flags); + if (name) node.name = name; + return node; + } + export function createEnumMember(name?: DeclarationName, initializer?: Expression, location?: TextRange, flags?: NodeFlags): EnumMember { + let node = createNode(SyntaxKind.EnumMember, location, flags); + if (name) node.name = name; + if (initializer) node.initializer = initializer; + return node; + } + export function createSourceFileNode(statements?: Array, endOfFileToken?: Node, fileName?: string, text?: string, amdDependencies?: Array, moduleName?: string, referencedFiles?: Array, languageVariant?: LanguageVariant, renamedDependencies?: Map, hasNoDefaultLib?: boolean, languageVersion?: ScriptTarget, externalModuleIndicator?: Node, isDefaultLib?: boolean, identifiers?: Map, parseDiagnostics?: Array, bindDiagnostics?: Array, lineMap?: Array, classifiableNames?: Map, resolvedModules?: Map, imports?: Array, location?: TextRange, flags?: NodeFlags): SourceFile { + let node = createNode(SyntaxKind.SourceFile, location, flags); + if (statements) node.statements = createNodeArray(statements); + if (endOfFileToken) node.endOfFileToken = endOfFileToken; + if (fileName) node.fileName = fileName; + if (text) node.text = text; + if (amdDependencies) node.amdDependencies = amdDependencies; + if (moduleName) node.moduleName = moduleName; + if (referencedFiles) node.referencedFiles = referencedFiles; + if (languageVariant) node.languageVariant = languageVariant; + if (renamedDependencies) node.renamedDependencies = renamedDependencies; + if (hasNoDefaultLib) node.hasNoDefaultLib = hasNoDefaultLib; + if (languageVersion) node.languageVersion = languageVersion; + if (externalModuleIndicator) node.externalModuleIndicator = externalModuleIndicator; + if (isDefaultLib) node.isDefaultLib = isDefaultLib; + if (identifiers) node.identifiers = identifiers; + if (parseDiagnostics) node.parseDiagnostics = parseDiagnostics; + if (bindDiagnostics) node.bindDiagnostics = bindDiagnostics; + if (lineMap) node.lineMap = lineMap; + if (classifiableNames) node.classifiableNames = classifiableNames; + if (resolvedModules) node.resolvedModules = resolvedModules; + if (imports) node.imports = imports; + return node; + } + export function createJSDocTypeExpression(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocTypeExpression { + let node = createNode(SyntaxKind.JSDocTypeExpression, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocAllType(location?: TextRange, flags?: NodeFlags): JSDocAllType { + let node = createNode(SyntaxKind.JSDocAllType, location, flags); + return node; + } + export function createJSDocUnknownType(location?: TextRange, flags?: NodeFlags): JSDocUnknownType { + let node = createNode(SyntaxKind.JSDocUnknownType, location, flags); + return node; + } + export function createJSDocArrayType(elementType?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocArrayType { + let node = createNode(SyntaxKind.JSDocArrayType, location, flags); + if (elementType) node.elementType = elementType; + return node; + } + export function createJSDocUnionType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocUnionType { + let node = createNode(SyntaxKind.JSDocUnionType, location, flags); + if (types) node.types = createNodeArray(types); + return node; + } + export function createJSDocTupleType(types?: Array, location?: TextRange, flags?: NodeFlags): JSDocTupleType { + let node = createNode(SyntaxKind.JSDocTupleType, location, flags); + if (types) node.types = createNodeArray(types); + return node; + } + export function createJSDocNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNullableType { + let node = createNode(SyntaxKind.JSDocNullableType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocNonNullableType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocNonNullableType { + let node = createNode(SyntaxKind.JSDocNonNullableType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocRecordType(members?: Array, location?: TextRange, flags?: NodeFlags): JSDocRecordType { + let node = createNode(SyntaxKind.JSDocRecordType, location, flags); + if (members) node.members = createNodeArray(members); + return node; + } + export function createJSDocRecordMember(name?: Identifier | LiteralExpression, type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocRecordMember { + let node = createNode(SyntaxKind.JSDocRecordMember, location, flags); + if (name) node.name = name; + if (type) node.type = type; + return node; + } + export function createJSDocTypeReference(name?: EntityName, typeArguments?: Array, location?: TextRange, flags?: NodeFlags): JSDocTypeReference { + let node = createNode(SyntaxKind.JSDocTypeReference, location, flags); + if (name) node.name = name; + if (typeArguments) node.typeArguments = createNodeArray(typeArguments); + return node; + } + export function createJSDocOptionalType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocOptionalType { + let node = createNode(SyntaxKind.JSDocOptionalType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocFunctionType(parameters?: Array, type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocFunctionType { + let node = createNode(SyntaxKind.JSDocFunctionType, location, flags); + if (parameters) node.parameters = createNodeArray(parameters); + if (type) node.type = type; + return node; + } + export function createJSDocVariadicType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocVariadicType { + let node = createNode(SyntaxKind.JSDocVariadicType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocConstructorType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocConstructorType { + let node = createNode(SyntaxKind.JSDocConstructorType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocThisType(type?: JSDocType, location?: TextRange, flags?: NodeFlags): JSDocThisType { + let node = createNode(SyntaxKind.JSDocThisType, location, flags); + if (type) node.type = type; + return node; + } + export function createJSDocComment(tags?: Array, location?: TextRange, flags?: NodeFlags): JSDocComment { + let node = createNode(SyntaxKind.JSDocComment, location, flags); + if (tags) node.tags = createNodeArray(tags); + return node; + } + export function createJSDocTag(atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTag { + let node = createNode(SyntaxKind.JSDocTag, location, flags); + if (atToken) node.atToken = atToken; + if (tagName) node.tagName = tagName; + return node; + } + export function createJSDocParameterTag(preParameterName?: Identifier, typeExpression?: JSDocTypeExpression, postParameterName?: Identifier, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocParameterTag { + let node = createNode(SyntaxKind.JSDocParameterTag, location, flags); + if (preParameterName) node.preParameterName = preParameterName; + if (typeExpression) node.typeExpression = typeExpression; + if (postParameterName) node.postParameterName = postParameterName; + if (atToken) node.atToken = atToken; + if (tagName) node.tagName = tagName; + return node; + } + export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocReturnTag { + let node = createNode(SyntaxKind.JSDocReturnTag, location, flags); + if (typeExpression) node.typeExpression = typeExpression; + if (atToken) node.atToken = atToken; + if (tagName) node.tagName = tagName; + return node; + } + export function createJSDocTypeTag(typeExpression?: JSDocTypeExpression, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTypeTag { + let node = createNode(SyntaxKind.JSDocTypeTag, location, flags); + if (typeExpression) node.typeExpression = typeExpression; + if (atToken) node.atToken = atToken; + if (tagName) node.tagName = tagName; + return node; + } + export function createJSDocTemplateTag(typeParameters?: Array, atToken?: Node, tagName?: Identifier, location?: TextRange, flags?: NodeFlags): JSDocTemplateTag { + let node = createNode(SyntaxKind.JSDocTemplateTag, location, flags); + if (typeParameters) node.typeParameters = createNodeArray(typeParameters); + if (atToken) node.atToken = atToken; + if (tagName) node.tagName = tagName; + return node; + } + export function createRawExpression(text?: string, location?: TextRange, flags?: NodeFlags): RawExpression { + let node = createNode(SyntaxKind.RawExpression, location, flags); + if (text) node.text = text; + return node; + } + export function createRawStatement(text?: string, location?: TextRange, flags?: NodeFlags): RawStatement { + let node = createNode(SyntaxKind.RawStatement, location, flags); + if (text) node.text = text; + return node; + } + export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName { + if (left !== node.left || right !== node.right) { + let newNode = createQualifiedName(left, right); + return updateFrom(node, newNode); + } + return node; + } + export function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName { + if (expression !== node.expression) { + let newNode = createComputedPropertyName(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeParameter(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode, expression: Expression): TypeParameterDeclaration { + if (name !== node.name || constraint !== node.constraint || expression !== node.expression) { + let newNode = createTypeParameter(name, constraint, expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateParameter(node: ParameterDeclaration, decorators: Array, modifiers: Array, name: BindingPattern | Identifier, questionToken: Node, type: TypeNode, initializer: Expression): ParameterDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || questionToken !== node.questionToken || type !== node.type || initializer !== node.initializer) { + let newNode = createParameter(decorators, modifiers, node.dotDotDotToken, name, questionToken, type, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateDecorator(node: Decorator, expression: LeftHandSideExpression): Decorator { + if (expression !== node.expression) { + let newNode = createDecorator(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updatePropertySignature(node: PropertySignature, decorators: Array, modifiers: Array, name: PropertyName, type: TypeNode): PropertySignature { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type) { + let newNode = createPropertySignature(decorators, modifiers, name, node.questionToken, type); + return updateFrom(node, newNode); + } + return node; + } + export function updatePropertyDeclaration(node: PropertyDeclaration, decorators: Array, modifiers: Array, name: PropertyName, type: TypeNode, initializer: Expression): PropertyDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || type !== node.type || initializer !== node.initializer) { + let newNode = createPropertyDeclaration(decorators, modifiers, name, type, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateMethodSignature(node: MethodSignature, decorators: Array, modifiers: Array, name: PropertyName, typeParameters: Array, parameters: Array, type: TypeNode): MethodSignature { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { + let newNode = createMethodSignature(decorators, modifiers, name, node.questionToken, typeParameters, parameters, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateMethodDeclaration(node: MethodDeclaration, decorators: Array, modifiers: Array, name: PropertyName, typeParameters: Array, parameters: Array, type: TypeNode, body: FunctionBody): MethodDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createMethodDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateConstructor(node: ConstructorDeclaration, decorators: Array, modifiers: Array, parameters: Array, type: TypeNode, body: FunctionBody): ConstructorDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createConstructor(decorators, modifiers, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Array, modifiers: Array, name: PropertyName, parameters: Array, type: TypeNode, body: FunctionBody): GetAccessorDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createGetAccessor(decorators, modifiers, name, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Array, modifiers: Array, name: PropertyName, parameters: Array, type: TypeNode, body: FunctionBody): SetAccessorDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createSetAccessor(decorators, modifiers, name, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateCallSignature(node: CallSignatureDeclaration, typeParameters: Array, parameters: Array, type: TypeNode): CallSignatureDeclaration { + if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { + let newNode = createCallSignature(typeParameters, parameters, type, node.questionToken); + return updateFrom(node, newNode); + } + return node; + } + export function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: Array, parameters: Array, type: TypeNode): ConstructSignatureDeclaration { + if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { + let newNode = createConstructSignature(typeParameters, parameters, type, node.questionToken); + return updateFrom(node, newNode); + } + return node; + } + export function updateIndexSignature(node: IndexSignatureDeclaration, decorators: Array, modifiers: Array, parameters: Array, type: TypeNode): IndexSignatureDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || parameters !== node.parameters || type !== node.type) { + let newNode = createIndexSignature(decorators, modifiers, parameters, type, node.questionToken); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypePredicate(node: TypePredicateNode, parameterName: Identifier, type: TypeNode): TypePredicateNode { + if (parameterName !== node.parameterName || type !== node.type) { + let newNode = createTypePredicate(parameterName, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeReference(node: TypeReferenceNode, typeName: EntityName, typeArguments: Array): TypeReferenceNode { + if (typeName !== node.typeName || typeArguments !== node.typeArguments) { + let newNode = createTypeReference(typeName, typeArguments); + return updateFrom(node, newNode); + } + return node; + } + export function updateFunctionType(node: FunctionTypeNode, typeParameters: Array, parameters: Array, type: TypeNode): FunctionTypeNode { + if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { + let newNode = createFunctionType(typeParameters, parameters, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateConstructorType(node: ConstructorTypeNode, typeParameters: Array, parameters: Array, type: TypeNode): ConstructorTypeNode { + if (typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type) { + let newNode = createConstructorType(typeParameters, parameters, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeQuery(node: TypeQueryNode, exprName: EntityName): TypeQueryNode { + if (exprName !== node.exprName) { + let newNode = createTypeQuery(exprName); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeLiteral(node: TypeLiteralNode, members: Array): TypeLiteralNode { + if (members !== node.members) { + let newNode = createTypeLiteral(members); + return updateFrom(node, newNode); + } + return node; + } + export function updateArrayType(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { + if (elementType !== node.elementType) { + let newNode = createArrayType(elementType); + return updateFrom(node, newNode); + } + return node; + } + export function updateTupleType(node: TupleTypeNode, elementTypes: Array): TupleTypeNode { + if (elementTypes !== node.elementTypes) { + let newNode = createTupleType(elementTypes); + return updateFrom(node, newNode); + } + return node; + } + export function updateUnionType(node: UnionTypeNode, types: Array): UnionTypeNode { + if (types !== node.types) { + let newNode = createUnionType(types); + return updateFrom(node, newNode); + } + return node; + } + export function updateIntersectionType(node: IntersectionTypeNode, types: Array): IntersectionTypeNode { + if (types !== node.types) { + let newNode = createIntersectionType(types); + return updateFrom(node, newNode); + } + return node; + } + export function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode { + if (type !== node.type) { + let newNode = createParenthesizedType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateObjectBindingPattern(node: ObjectBindingPattern, elements: Array): ObjectBindingPattern { + if (elements !== node.elements) { + let newNode = createObjectBindingPattern(elements); + return updateFrom(node, newNode); + } + return node; + } + export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: Array): ArrayBindingPattern { + if (elements !== node.elements) { + let newNode = createArrayBindingPattern(elements); + return updateFrom(node, newNode); + } + return node; + } + export function updateBindingElement(node: BindingElement, propertyName: Identifier, name: BindingPattern | Identifier, initializer: Expression): BindingElement { + if (propertyName !== node.propertyName || name !== node.name || initializer !== node.initializer) { + let newNode = createBindingElement(propertyName, node.dotDotDotToken, name, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: Array): ArrayLiteralExpression { + if (elements !== node.elements) { + let newNode = createArrayLiteralExpression(elements); + return updateFrom(node, newNode); + } + return node; + } + export function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: Array): ObjectLiteralExpression { + if (properties !== node.properties) { + let newNode = createObjectLiteralExpression(properties); + return updateFrom(node, newNode); + } + return node; + } + export function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: LeftHandSideExpression, name: Identifier): PropertyAccessExpression { + if (expression !== node.expression || name !== node.name) { + let newNode = createPropertyAccessExpression(expression, node.dotToken, name); + return updateFrom(node, newNode); + } + return node; + } + export function updateElementAccessExpression(node: ElementAccessExpression, expression: LeftHandSideExpression, argumentExpression: Expression): ElementAccessExpression { + if (expression !== node.expression || argumentExpression !== node.argumentExpression) { + let newNode = createElementAccessExpression(expression, argumentExpression); + return updateFrom(node, newNode); + } + return node; + } + export function updateCallExpression(node: CallExpression, expression: LeftHandSideExpression, typeArguments: Array, _arguments: Array): CallExpression { + if (expression !== node.expression || typeArguments !== node.typeArguments || _arguments !== node.arguments) { + let newNode = createCallExpression(expression, typeArguments, _arguments); + return updateFrom(node, newNode); + } + return node; + } + export function updateNewExpression(node: NewExpression, expression: LeftHandSideExpression, typeArguments: Array, _arguments: Array): NewExpression { + if (expression !== node.expression || typeArguments !== node.typeArguments || _arguments !== node.arguments) { + let newNode = createNewExpression(expression, typeArguments, _arguments); + return updateFrom(node, newNode); + } + return node; + } + export function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: LeftHandSideExpression, template: LiteralExpression | TemplateExpression): TaggedTemplateExpression { + if (tag !== node.tag || template !== node.template) { + let newNode = createTaggedTemplateExpression(tag, template); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeAssertionExpression(node: TypeAssertion, type: TypeNode, expression: UnaryExpression): TypeAssertion { + if (type !== node.type || expression !== node.expression) { + let newNode = createTypeAssertionExpression(type, expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression { + if (expression !== node.expression) { + let newNode = createParenthesizedExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateFunctionExpression(node: FunctionExpression, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, parameters: Array, type: TypeNode, body: FunctionBody): FunctionExpression { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createFunctionExpression(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateArrowFunction(node: ArrowFunction, decorators: Array, modifiers: Array, typeParameters: Array, parameters: Array, type: TypeNode, body: ConciseBody): ArrowFunction { + if (decorators !== node.decorators || modifiers !== node.modifiers || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createArrowFunction(decorators, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateDeleteExpression(node: DeleteExpression, expression: UnaryExpression): DeleteExpression { + if (expression !== node.expression) { + let newNode = createDeleteExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeOfExpression(node: TypeOfExpression, expression: UnaryExpression): TypeOfExpression { + if (expression !== node.expression) { + let newNode = createTypeOfExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateVoidExpression(node: VoidExpression, expression: UnaryExpression): VoidExpression { + if (expression !== node.expression) { + let newNode = createVoidExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateAwaitExpression(node: AwaitExpression, expression: UnaryExpression): AwaitExpression { + if (expression !== node.expression) { + let newNode = createAwaitExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: UnaryExpression): PrefixUnaryExpression { + if (operand !== node.operand) { + let newNode = createPrefixUnaryExpression(node.operator, operand); + return updateFrom(node, newNode); + } + return node; + } + export function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: LeftHandSideExpression): PostfixUnaryExpression { + if (operand !== node.operand) { + let newNode = createPostfixUnaryExpression(operand, node.operator); + return updateFrom(node, newNode); + } + return node; + } + export function updateBinaryExpression(node: BinaryExpression, left: Expression, right: Expression): BinaryExpression { + if (left !== node.left || right !== node.right) { + let newNode = createBinaryExpression(left, node.operatorToken, right); + return updateFrom(node, newNode); + } + return node; + } + export function updateConditionalExpression(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression { + if (condition !== node.condition || whenTrue !== node.whenTrue || whenFalse !== node.whenFalse) { + let newNode = createConditionalExpression(condition, node.questionToken, whenTrue, node.colonToken, whenFalse); + return updateFrom(node, newNode); + } + return node; + } + export function updateTemplateExpression(node: TemplateExpression, head: LiteralExpression, templateSpans: Array): TemplateExpression { + if (head !== node.head || templateSpans !== node.templateSpans) { + let newNode = createTemplateExpression(head, templateSpans); + return updateFrom(node, newNode); + } + return node; + } + export function updateYieldExpression(node: YieldExpression, expression: Expression): YieldExpression { + if (expression !== node.expression) { + let newNode = createYieldExpression(node.asteriskToken, expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateSpreadElementExpression(node: SpreadElementExpression, expression: Expression): SpreadElementExpression { + if (expression !== node.expression) { + let newNode = createSpreadElementExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateClassExpression(node: ClassExpression, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, heritageClauses: Array, members: Array): ClassExpression { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || heritageClauses !== node.heritageClauses || members !== node.members) { + let newNode = createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members); + return updateFrom(node, newNode); + } + return node; + } + export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: LeftHandSideExpression, typeArguments: Array): ExpressionWithTypeArguments { + if (expression !== node.expression || typeArguments !== node.typeArguments) { + let newNode = createExpressionWithTypeArguments(expression, typeArguments); + return updateFrom(node, newNode); + } + return node; + } + export function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression { + if (expression !== node.expression || type !== node.type) { + let newNode = createAsExpression(expression, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: LiteralExpression): TemplateSpan { + if (expression !== node.expression || literal !== node.literal) { + let newNode = createTemplateSpan(expression, literal); + return updateFrom(node, newNode); + } + return node; + } + export function updateBlock(node: Block, statements: Array): Block { + if (statements !== node.statements) { + let newNode = createBlock(statements); + return updateFrom(node, newNode); + } + return node; + } + 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; + } + export function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement { + if (expression !== node.expression) { + let newNode = createExpressionStatement(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement): IfStatement { + if (expression !== node.expression || thenStatement !== node.thenStatement || elseStatement !== node.elseStatement) { + let newNode = createIfStatement(expression, thenStatement, elseStatement); + return updateFrom(node, newNode); + } + return node; + } + export function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression): DoStatement { + if (statement !== node.statement || expression !== node.expression) { + let newNode = createDoStatement(statement, expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement { + if (expression !== node.expression || statement !== node.statement) { + let newNode = createWhileStatement(expression, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateForStatement(node: ForStatement, initializer: Expression | VariableDeclarationList, condition: Expression, incrementor: Expression, statement: Statement): ForStatement { + if (initializer !== node.initializer || condition !== node.condition || incrementor !== node.incrementor || statement !== node.statement) { + let newNode = createForStatement(initializer, condition, incrementor, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateForInStatement(node: ForInStatement, initializer: Expression | VariableDeclarationList, expression: Expression, statement: Statement): ForInStatement { + if (initializer !== node.initializer || expression !== node.expression || statement !== node.statement) { + let newNode = createForInStatement(initializer, expression, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateForOfStatement(node: ForOfStatement, initializer: Expression | VariableDeclarationList, expression: Expression, statement: Statement): ForOfStatement { + if (initializer !== node.initializer || expression !== node.expression || statement !== node.statement) { + let newNode = createForOfStatement(initializer, expression, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateContinueStatement(node: ContinueStatement, label: Identifier): ContinueStatement { + if (label !== node.label) { + let newNode = createContinueStatement(label); + return updateFrom(node, newNode); + } + return node; + } + export function updateBreakStatement(node: BreakStatement, label: Identifier): BreakStatement { + if (label !== node.label) { + let newNode = createBreakStatement(label); + return updateFrom(node, newNode); + } + return node; + } + export function updateReturnStatement(node: ReturnStatement, expression: Expression): ReturnStatement { + if (expression !== node.expression) { + let newNode = createReturnStatement(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement): WithStatement { + if (expression !== node.expression || statement !== node.statement) { + let newNode = createWithStatement(expression, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement { + if (expression !== node.expression || caseBlock !== node.caseBlock) { + let newNode = createSwitchStatement(expression, caseBlock); + return updateFrom(node, newNode); + } + return node; + } + export function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement { + if (label !== node.label || statement !== node.statement) { + let newNode = createLabeledStatement(label, statement); + return updateFrom(node, newNode); + } + return node; + } + export function updateThrowStatement(node: ThrowStatement, expression: Expression): ThrowStatement { + if (expression !== node.expression) { + let newNode = createThrowStatement(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block): TryStatement { + if (tryBlock !== node.tryBlock || catchClause !== node.catchClause || finallyBlock !== node.finallyBlock) { + let newNode = createTryStatement(tryBlock, catchClause, finallyBlock); + return updateFrom(node, newNode); + } + return node; + } + 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; + } + export function updateVariableDeclarationList(node: VariableDeclarationList, declarations: Array): VariableDeclarationList { + if (declarations !== node.declarations) { + let newNode = createVariableDeclarationList(declarations); + return updateFrom(node, newNode); + } + return node; + } + export function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, parameters: Array, type: TypeNode, body: FunctionBody): FunctionDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || parameters !== node.parameters || type !== node.type || body !== node.body) { + let newNode = createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateClassDeclaration(node: ClassDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, heritageClauses: Array, members: Array): ClassDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || heritageClauses !== node.heritageClauses || members !== node.members) { + let newNode = createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); + return updateFrom(node, newNode); + } + return node; + } + export function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, heritageClauses: Array, members: Array): InterfaceDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || heritageClauses !== node.heritageClauses || members !== node.members) { + let newNode = createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); + return updateFrom(node, newNode); + } + return node; + } + export function updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: Array, modifiers: Array, name: Identifier, typeParameters: Array, type: TypeNode): TypeAliasDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || typeParameters !== node.typeParameters || type !== node.type) { + let newNode = createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateEnumDeclaration(node: EnumDeclaration, decorators: Array, modifiers: Array, name: Identifier, members: Array): EnumDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || members !== node.members) { + let newNode = createEnumDeclaration(decorators, modifiers, name, members); + return updateFrom(node, newNode); + } + return node; + } + export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Array, modifiers: Array, name: Identifier | LiteralExpression, body: ModuleBody): ModuleDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || body !== node.body) { + let newNode = createModuleDeclaration(decorators, modifiers, name, body); + return updateFrom(node, newNode); + } + return node; + } + export function updateModuleBlock(node: ModuleBlock, statements: Array): ModuleBlock { + if (statements !== node.statements) { + let newNode = createModuleBlock(statements); + return updateFrom(node, newNode); + } + return node; + } + export function updateCaseBlock(node: CaseBlock, clauses: Array): CaseBlock { + if (clauses !== node.clauses) { + let newNode = createCaseBlock(clauses); + return updateFrom(node, newNode); + } + return node; + } + export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Array, modifiers: Array, name: Identifier, moduleReference: EntityName | ExternalModuleReference): ImportEqualsDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || name !== node.name || moduleReference !== node.moduleReference) { + let newNode = createImportEqualsDeclaration(decorators, modifiers, name, moduleReference); + return updateFrom(node, newNode); + } + return node; + } + export function updateImportDeclaration(node: ImportDeclaration, decorators: Array, modifiers: Array, importClause: ImportClause, moduleSpecifier: Expression): ImportDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || importClause !== node.importClause || moduleSpecifier !== node.moduleSpecifier) { + let newNode = createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier); + return updateFrom(node, newNode); + } + return node; + } + export function updateImportClause(node: ImportClause, name: Identifier, namedBindings: NamedImports | NamespaceImport): ImportClause { + if (name !== node.name || namedBindings !== node.namedBindings) { + let newNode = createImportClause(name, namedBindings); + return updateFrom(node, newNode); + } + return node; + } + export function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport { + if (name !== node.name) { + let newNode = createNamespaceImport(name); + return updateFrom(node, newNode); + } + return node; + } + export function updateNamedImports(node: NamedImports, elements: Array): NamedImports { + if (elements !== node.elements) { + let newNode = createNamedImports(elements); + return updateFrom(node, newNode); + } + return node; + } + export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier): ImportSpecifier { + if (propertyName !== node.propertyName || name !== node.name) { + let newNode = createImportSpecifier(propertyName, name); + return updateFrom(node, newNode); + } + return node; + } + export function updateExportAssignment(node: ExportAssignment, decorators: Array, modifiers: Array, expression: Expression): ExportAssignment { + if (decorators !== node.decorators || modifiers !== node.modifiers || expression !== node.expression) { + let newNode = createExportAssignment(decorators, modifiers, expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateExportDeclaration(node: ExportDeclaration, decorators: Array, modifiers: Array, exportClause: NamedExports, moduleSpecifier: Expression): ExportDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers || exportClause !== node.exportClause || moduleSpecifier !== node.moduleSpecifier) { + let newNode = createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier); + return updateFrom(node, newNode); + } + return node; + } + export function updateNamedExports(node: NamedExports, elements: Array): NamedExports { + if (elements !== node.elements) { + let newNode = createNamedExports(elements); + return updateFrom(node, newNode); + } + return node; + } + export function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier, name: Identifier): ExportSpecifier { + if (propertyName !== node.propertyName || name !== node.name) { + let newNode = createExportSpecifier(propertyName, name); + return updateFrom(node, newNode); + } + return node; + } + export function updateMissingDeclaration(node: MissingDeclaration, decorators: Array, modifiers: Array): MissingDeclaration { + if (decorators !== node.decorators || modifiers !== node.modifiers) { + let newNode = createMissingDeclaration(decorators, modifiers, node.questionToken); + return updateFrom(node, newNode); + } + return node; + } + export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference { + if (expression !== node.expression) { + let newNode = createExternalModuleReference(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: Array, closingElement: JsxClosingElement): JsxElement { + if (openingElement !== node.openingElement || children !== node.children || closingElement !== node.closingElement) { + let newNode = createJsxElement(openingElement, children, closingElement); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: EntityName, attributes: Array): JsxSelfClosingElement { + if (tagName !== node.tagName || attributes !== node.attributes) { + let newNode = createJsxSelfClosingElement(tagName, attributes); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: EntityName, attributes: Array): JsxOpeningElement { + if (tagName !== node.tagName || attributes !== node.attributes) { + let newNode = createJsxOpeningElement(tagName, attributes); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxClosingElement(node: JsxClosingElement, tagName: EntityName): JsxClosingElement { + if (tagName !== node.tagName) { + let newNode = createJsxClosingElement(tagName); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: Expression): JsxAttribute { + if (name !== node.name || initializer !== node.initializer) { + let newNode = createJsxAttribute(name, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute { + if (expression !== node.expression) { + let newNode = createJsxSpreadAttribute(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateJsxExpression(node: JsxExpression, expression: Expression): JsxExpression { + if (expression !== node.expression) { + let newNode = createJsxExpression(expression); + return updateFrom(node, newNode); + } + return node; + } + export function updateCaseClause(node: CaseClause, expression: Expression, statements: Array): CaseClause { + if (expression !== node.expression || statements !== node.statements) { + let newNode = createCaseClause(expression, statements); + return updateFrom(node, newNode); + } + return node; + } + export function updateDefaultClause(node: DefaultClause, statements: Array): DefaultClause { + if (statements !== node.statements) { + let newNode = createDefaultClause(statements); + return updateFrom(node, newNode); + } + return node; + } + export function updateHeritageClause(node: HeritageClause, types: Array): HeritageClause { + if (types !== node.types) { + let newNode = createHeritageClause(node.token, types); + return updateFrom(node, newNode); + } + return node; + } + export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block): CatchClause { + if (variableDeclaration !== node.variableDeclaration || block !== node.block) { + let newNode = createCatchClause(variableDeclaration, block); + return updateFrom(node, newNode); + } + return node; + } + export function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment { + if (name !== node.name || initializer !== node.initializer) { + let newNode = createPropertyAssignment(name, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier): ShorthandPropertyAssignment { + if (name !== node.name) { + let newNode = createShorthandPropertyAssignment(name); + return updateFrom(node, newNode); + } + return node; + } + export function updateEnumMember(node: EnumMember, name: DeclarationName, initializer: Expression): EnumMember { + if (name !== node.name || initializer !== node.initializer) { + let newNode = createEnumMember(name, initializer); + return updateFrom(node, newNode); + } + return node; + } + export function updateSourceFileNode(node: SourceFile, statements: Array, endOfFileToken: Node): SourceFile { + if (statements !== node.statements || endOfFileToken !== node.endOfFileToken) { + let newNode = createSourceFileNode(statements, endOfFileToken, node.fileName, node.text, node.amdDependencies, node.moduleName, node.referencedFiles, node.languageVariant, node.renamedDependencies, node.hasNoDefaultLib, node.languageVersion, node.externalModuleIndicator, node.isDefaultLib, node.identifiers, node.parseDiagnostics, node.bindDiagnostics, node.lineMap, node.classifiableNames, node.resolvedModules, node.imports); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTypeExpression(node: JSDocTypeExpression, type: JSDocType): JSDocTypeExpression { + if (type !== node.type) { + let newNode = createJSDocTypeExpression(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocArrayType(node: JSDocArrayType, elementType: JSDocType): JSDocArrayType { + if (elementType !== node.elementType) { + let newNode = createJSDocArrayType(elementType); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocUnionType(node: JSDocUnionType, types: Array): JSDocUnionType { + if (types !== node.types) { + let newNode = createJSDocUnionType(types); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTupleType(node: JSDocTupleType, types: Array): JSDocTupleType { + if (types !== node.types) { + let newNode = createJSDocTupleType(types); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocNullableType(node: JSDocNullableType, type: JSDocType): JSDocNullableType { + if (type !== node.type) { + let newNode = createJSDocNullableType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocNonNullableType(node: JSDocNonNullableType, type: JSDocType): JSDocNonNullableType { + if (type !== node.type) { + let newNode = createJSDocNonNullableType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocRecordType(node: JSDocRecordType, members: Array): JSDocRecordType { + if (members !== node.members) { + let newNode = createJSDocRecordType(members); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocRecordMember(node: JSDocRecordMember, name: Identifier | LiteralExpression, type: JSDocType): JSDocRecordMember { + if (name !== node.name || type !== node.type) { + let newNode = createJSDocRecordMember(name, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTypeReference(node: JSDocTypeReference, name: EntityName, typeArguments: Array): JSDocTypeReference { + if (name !== node.name || typeArguments !== node.typeArguments) { + let newNode = createJSDocTypeReference(name, typeArguments); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocOptionalType(node: JSDocOptionalType, type: JSDocType): JSDocOptionalType { + if (type !== node.type) { + let newNode = createJSDocOptionalType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocFunctionType(node: JSDocFunctionType, parameters: Array, type: JSDocType): JSDocFunctionType { + if (parameters !== node.parameters || type !== node.type) { + let newNode = createJSDocFunctionType(parameters, type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocVariadicType(node: JSDocVariadicType, type: JSDocType): JSDocVariadicType { + if (type !== node.type) { + let newNode = createJSDocVariadicType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocConstructorType(node: JSDocConstructorType, type: JSDocType): JSDocConstructorType { + if (type !== node.type) { + let newNode = createJSDocConstructorType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocThisType(node: JSDocThisType, type: JSDocType): JSDocThisType { + if (type !== node.type) { + let newNode = createJSDocThisType(type); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocComment(node: JSDocComment, tags: Array): JSDocComment { + if (tags !== node.tags) { + let newNode = createJSDocComment(tags); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTag(node: JSDocTag, tagName: Identifier): JSDocTag { + if (tagName !== node.tagName) { + let newNode = createJSDocTag(node.atToken, tagName); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocParameterTag(node: JSDocParameterTag, preParameterName: Identifier, typeExpression: JSDocTypeExpression, postParameterName: Identifier, tagName: Identifier): JSDocParameterTag { + if (preParameterName !== node.preParameterName || typeExpression !== node.typeExpression || postParameterName !== node.postParameterName || tagName !== node.tagName) { + let newNode = createJSDocParameterTag(preParameterName, typeExpression, postParameterName, node.atToken, tagName); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocReturnTag(node: JSDocReturnTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocReturnTag { + if (typeExpression !== node.typeExpression || tagName !== node.tagName) { + let newNode = createJSDocReturnTag(typeExpression, node.atToken, tagName); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTypeTag(node: JSDocTypeTag, typeExpression: JSDocTypeExpression, tagName: Identifier): JSDocTypeTag { + if (typeExpression !== node.typeExpression || tagName !== node.tagName) { + let newNode = createJSDocTypeTag(typeExpression, node.atToken, tagName); + return updateFrom(node, newNode); + } + return node; + } + export function updateJSDocTemplateTag(node: JSDocTemplateTag, typeParameters: Array, tagName: Identifier): JSDocTemplateTag { + if (typeParameters !== node.typeParameters || tagName !== node.tagName) { + let newNode = createJSDocTemplateTag(typeParameters, node.atToken, tagName); + return updateFrom(node, newNode); + } + return node; + } + export function isNumericLiteral(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.NumericLiteral; + } + export function isStringLiteral(node: Node): node is StringLiteral { + return node && node.kind === SyntaxKind.StringLiteral; + } + export function isRegularExpressionLiteral(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.RegularExpressionLiteral; + } + export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; + } + export function isTemplateHead(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.TemplateHead; + } + export function isTemplateMiddle(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.TemplateMiddle; + } + export function isTemplateTail(node: Node): node is LiteralExpression { + return node && node.kind === SyntaxKind.TemplateTail; + } + export function isIdentifier(node: Node): node is Identifier { + return node && node.kind === SyntaxKind.Identifier; + } + export function isFalseKeyword(node: Node): node is PrimaryExpression { + return node && node.kind === SyntaxKind.FalseKeyword; + } + export function isNullKeyword(node: Node): node is PrimaryExpression { + return node && node.kind === SyntaxKind.NullKeyword; + } + export function isSuperKeyword(node: Node): node is PrimaryExpression { + return node && node.kind === SyntaxKind.SuperKeyword; + } + export function isThisKeyword(node: Node): node is PrimaryExpression { + return node && node.kind === SyntaxKind.ThisKeyword; + } + export function isTrueKeyword(node: Node): node is PrimaryExpression { + return node && node.kind === SyntaxKind.TrueKeyword; + } + export function isQualifiedName(node: Node): node is QualifiedName { + return node && node.kind === SyntaxKind.QualifiedName; + } + export function isComputedPropertyName(node: Node): node is ComputedPropertyName { + return node && node.kind === SyntaxKind.ComputedPropertyName; + } + export function isTypeParameter(node: Node): node is TypeParameterDeclaration { + return node && node.kind === SyntaxKind.TypeParameter; + } + export function isParameter(node: Node): node is ParameterDeclaration { + return node && node.kind === SyntaxKind.Parameter; + } + export function isDecorator(node: Node): node is Decorator { + return node && node.kind === SyntaxKind.Decorator; + } + export function isPropertySignature(node: Node): node is PropertySignature { + return node && node.kind === SyntaxKind.PropertySignature; + } + export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { + return node && node.kind === SyntaxKind.PropertyDeclaration; + } + export function isMethodSignature(node: Node): node is MethodSignature { + return node && node.kind === SyntaxKind.MethodSignature; + } + export function isMethodDeclaration(node: Node): node is MethodDeclaration { + return node && node.kind === SyntaxKind.MethodDeclaration; + } + export function isConstructor(node: Node): node is ConstructorDeclaration { + return node && node.kind === SyntaxKind.Constructor; + } + export function isGetAccessor(node: Node): node is GetAccessorDeclaration { + return node && node.kind === SyntaxKind.GetAccessor; + } + export function isSetAccessor(node: Node): node is SetAccessorDeclaration { + return node && node.kind === SyntaxKind.SetAccessor; + } + export function isCallSignature(node: Node): node is CallSignatureDeclaration { + return node && node.kind === SyntaxKind.CallSignature; + } + export function isConstructSignature(node: Node): node is ConstructSignatureDeclaration { + return node && node.kind === SyntaxKind.ConstructSignature; + } + export function isIndexSignature(node: Node): node is IndexSignatureDeclaration { + return node && node.kind === SyntaxKind.IndexSignature; + } + export function isTypePredicate(node: Node): node is TypePredicateNode { + return node && node.kind === SyntaxKind.TypePredicate; + } + export function isTypeReference(node: Node): node is TypeReferenceNode { + return node && node.kind === SyntaxKind.TypeReference; + } + export function isFunctionType(node: Node): node is FunctionTypeNode { + return node && node.kind === SyntaxKind.FunctionType; + } + export function isConstructorType(node: Node): node is ConstructorTypeNode { + return node && node.kind === SyntaxKind.ConstructorType; + } + export function isTypeQuery(node: Node): node is TypeQueryNode { + return node && node.kind === SyntaxKind.TypeQuery; + } + export function isTypeLiteral(node: Node): node is TypeLiteralNode { + return node && node.kind === SyntaxKind.TypeLiteral; + } + export function isArrayType(node: Node): node is ArrayTypeNode { + return node && node.kind === SyntaxKind.ArrayType; + } + export function isTupleType(node: Node): node is TupleTypeNode { + return node && node.kind === SyntaxKind.TupleType; + } + export function isUnionType(node: Node): node is UnionTypeNode { + return node && node.kind === SyntaxKind.UnionType; + } + export function isIntersectionType(node: Node): node is IntersectionTypeNode { + return node && node.kind === SyntaxKind.IntersectionType; + } + export function isParenthesizedType(node: Node): node is ParenthesizedTypeNode { + return node && node.kind === SyntaxKind.ParenthesizedType; + } + export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { + return node && node.kind === SyntaxKind.ObjectBindingPattern; + } + export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { + return node && node.kind === SyntaxKind.ArrayBindingPattern; + } + export function isBindingElement(node: Node): node is BindingElement { + return node && node.kind === SyntaxKind.BindingElement; + } + export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { + return node && node.kind === SyntaxKind.ArrayLiteralExpression; + } + export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { + return node && node.kind === SyntaxKind.ObjectLiteralExpression; + } + export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node && node.kind === SyntaxKind.PropertyAccessExpression; + } + export function isElementAccessExpression(node: Node): node is ElementAccessExpression { + return node && node.kind === SyntaxKind.ElementAccessExpression; + } + export function isCallExpression(node: Node): node is CallExpression { + return node && node.kind === SyntaxKind.CallExpression; + } + export function isNewExpression(node: Node): node is NewExpression { + return node && node.kind === SyntaxKind.NewExpression; + } + export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { + return node && node.kind === SyntaxKind.TaggedTemplateExpression; + } + export function isTypeAssertionExpression(node: Node): node is TypeAssertion { + return node && node.kind === SyntaxKind.TypeAssertionExpression; + } + export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { + return node && node.kind === SyntaxKind.ParenthesizedExpression; + } + export function isFunctionExpression(node: Node): node is FunctionExpression { + return node && node.kind === SyntaxKind.FunctionExpression; + } + export function isArrowFunction(node: Node): node is ArrowFunction { + return node && node.kind === SyntaxKind.ArrowFunction; + } + export function isDeleteExpression(node: Node): node is DeleteExpression { + return node && node.kind === SyntaxKind.DeleteExpression; + } + export function isTypeOfExpression(node: Node): node is TypeOfExpression { + return node && node.kind === SyntaxKind.TypeOfExpression; + } + export function isVoidExpression(node: Node): node is VoidExpression { + return node && node.kind === SyntaxKind.VoidExpression; + } + export function isAwaitExpression(node: Node): node is AwaitExpression { + return node && node.kind === SyntaxKind.AwaitExpression; + } + export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { + return node && node.kind === SyntaxKind.PrefixUnaryExpression; + } + export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { + return node && node.kind === SyntaxKind.PostfixUnaryExpression; + } + export function isBinaryExpression(node: Node): node is BinaryExpression { + return node && node.kind === SyntaxKind.BinaryExpression; + } + export function isConditionalExpression(node: Node): node is ConditionalExpression { + return node && node.kind === SyntaxKind.ConditionalExpression; + } + export function isTemplateExpression(node: Node): node is TemplateExpression { + return node && node.kind === SyntaxKind.TemplateExpression; + } + export function isYieldExpression(node: Node): node is YieldExpression { + return node && node.kind === SyntaxKind.YieldExpression; + } + export function isSpreadElementExpression(node: Node): node is SpreadElementExpression { + return node && node.kind === SyntaxKind.SpreadElementExpression; + } + export function isClassExpression(node: Node): node is ClassExpression { + return node && node.kind === SyntaxKind.ClassExpression; + } + export function isOmittedExpression(node: Node): node is OmittedExpression { + return node && node.kind === SyntaxKind.OmittedExpression; + } + export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { + return node && node.kind === SyntaxKind.ExpressionWithTypeArguments; + } + export function isAsExpression(node: Node): node is AsExpression { + return node && node.kind === SyntaxKind.AsExpression; + } + export function isTemplateSpan(node: Node): node is TemplateSpan { + return node && node.kind === SyntaxKind.TemplateSpan; + } + export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { + return node && node.kind === SyntaxKind.SemicolonClassElement; + } + export function isBlock(node: Node): node is Block { + return node && node.kind === SyntaxKind.Block; + } + export function isVariableStatement(node: Node): node is VariableStatement { + return node && node.kind === SyntaxKind.VariableStatement; + } + export function isEmptyStatement(node: Node): node is EmptyStatement { + return node && node.kind === SyntaxKind.EmptyStatement; + } + export function isExpressionStatement(node: Node): node is ExpressionStatement { + return node && node.kind === SyntaxKind.ExpressionStatement; + } + export function isIfStatement(node: Node): node is IfStatement { + return node && node.kind === SyntaxKind.IfStatement; + } + export function isDoStatement(node: Node): node is DoStatement { + return node && node.kind === SyntaxKind.DoStatement; + } + export function isWhileStatement(node: Node): node is WhileStatement { + return node && node.kind === SyntaxKind.WhileStatement; + } + export function isForStatement(node: Node): node is ForStatement { + return node && node.kind === SyntaxKind.ForStatement; + } + export function isForInStatement(node: Node): node is ForInStatement { + return node && node.kind === SyntaxKind.ForInStatement; + } + export function isForOfStatement(node: Node): node is ForOfStatement { + return node && node.kind === SyntaxKind.ForOfStatement; + } + export function isContinueStatement(node: Node): node is ContinueStatement { + return node && node.kind === SyntaxKind.ContinueStatement; + } + export function isBreakStatement(node: Node): node is BreakStatement { + return node && node.kind === SyntaxKind.BreakStatement; + } + export function isReturnStatement(node: Node): node is ReturnStatement { + return node && node.kind === SyntaxKind.ReturnStatement; + } + export function isWithStatement(node: Node): node is WithStatement { + return node && node.kind === SyntaxKind.WithStatement; + } + export function isSwitchStatement(node: Node): node is SwitchStatement { + return node && node.kind === SyntaxKind.SwitchStatement; + } + export function isLabeledStatement(node: Node): node is LabeledStatement { + return node && node.kind === SyntaxKind.LabeledStatement; + } + export function isThrowStatement(node: Node): node is ThrowStatement { + return node && node.kind === SyntaxKind.ThrowStatement; + } + export function isTryStatement(node: Node): node is TryStatement { + return node && node.kind === SyntaxKind.TryStatement; + } + export function isDebuggerStatement(node: Node): node is DebuggerStatement { + return node && node.kind === SyntaxKind.DebuggerStatement; + } + export function isVariableDeclaration(node: Node): node is VariableDeclaration { + return node && node.kind === SyntaxKind.VariableDeclaration; + } + export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { + return node && node.kind === SyntaxKind.VariableDeclarationList; + } + export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { + return node && node.kind === SyntaxKind.FunctionDeclaration; + } + export function isClassDeclaration(node: Node): node is ClassDeclaration { + return node && node.kind === SyntaxKind.ClassDeclaration; + } + export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { + return node && node.kind === SyntaxKind.InterfaceDeclaration; + } + export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { + return node && node.kind === SyntaxKind.TypeAliasDeclaration; + } + export function isEnumDeclaration(node: Node): node is EnumDeclaration { + return node && node.kind === SyntaxKind.EnumDeclaration; + } + export function isModuleDeclaration(node: Node): node is ModuleDeclaration { + return node && node.kind === SyntaxKind.ModuleDeclaration; + } + export function isModuleBlock(node: Node): node is ModuleBlock { + return node && node.kind === SyntaxKind.ModuleBlock; + } + export function isCaseBlock(node: Node): node is CaseBlock { + return node && node.kind === SyntaxKind.CaseBlock; + } + export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { + return node && node.kind === SyntaxKind.ImportEqualsDeclaration; + } + export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node && node.kind === SyntaxKind.ImportDeclaration; + } + export function isImportClause(node: Node): node is ImportClause { + return node && node.kind === SyntaxKind.ImportClause; + } + export function isNamespaceImport(node: Node): node is NamespaceImport { + return node && node.kind === SyntaxKind.NamespaceImport; + } + export function isNamedImports(node: Node): node is NamedImports { + return node && node.kind === SyntaxKind.NamedImports; + } + export function isImportSpecifier(node: Node): node is ImportSpecifier { + return node && node.kind === SyntaxKind.ImportSpecifier; + } + export function isExportAssignment(node: Node): node is ExportAssignment { + return node && node.kind === SyntaxKind.ExportAssignment; + } + export function isExportDeclaration(node: Node): node is ExportDeclaration { + return node && node.kind === SyntaxKind.ExportDeclaration; + } + export function isNamedExports(node: Node): node is NamedExports { + return node && node.kind === SyntaxKind.NamedExports; + } + export function isExportSpecifier(node: Node): node is ExportSpecifier { + return node && node.kind === SyntaxKind.ExportSpecifier; + } + export function isMissingDeclaration(node: Node): node is MissingDeclaration { + return node && node.kind === SyntaxKind.MissingDeclaration; + } + export function isExternalModuleReference(node: Node): node is ExternalModuleReference { + return node && node.kind === SyntaxKind.ExternalModuleReference; + } + export function isJsxElement(node: Node): node is JsxElement { + return node && node.kind === SyntaxKind.JsxElement; + } + export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { + return node && node.kind === SyntaxKind.JsxSelfClosingElement; + } + export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { + return node && node.kind === SyntaxKind.JsxOpeningElement; + } + export function isJsxText(node: Node): node is JsxText { + return node && node.kind === SyntaxKind.JsxText; + } + export function isJsxClosingElement(node: Node): node is JsxClosingElement { + return node && node.kind === SyntaxKind.JsxClosingElement; + } + export function isJsxAttribute(node: Node): node is JsxAttribute { + return node && node.kind === SyntaxKind.JsxAttribute; + } + export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { + return node && node.kind === SyntaxKind.JsxSpreadAttribute; + } + export function isJsxExpression(node: Node): node is JsxExpression { + return node && node.kind === SyntaxKind.JsxExpression; + } + export function isCaseClause(node: Node): node is CaseClause { + return node && node.kind === SyntaxKind.CaseClause; + } + export function isDefaultClause(node: Node): node is DefaultClause { + return node && node.kind === SyntaxKind.DefaultClause; + } + export function isHeritageClause(node: Node): node is HeritageClause { + return node && node.kind === SyntaxKind.HeritageClause; + } + export function isCatchClause(node: Node): node is CatchClause { + return node && node.kind === SyntaxKind.CatchClause; + } + export function isPropertyAssignment(node: Node): node is PropertyAssignment { + return node && node.kind === SyntaxKind.PropertyAssignment; + } + export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { + return node && node.kind === SyntaxKind.ShorthandPropertyAssignment; + } + export function isEnumMember(node: Node): node is EnumMember { + return node && node.kind === SyntaxKind.EnumMember; + } + export function isSourceFile(node: Node): node is SourceFile { + return node && node.kind === SyntaxKind.SourceFile; + } + export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { + return node && node.kind === SyntaxKind.JSDocTypeExpression; + } + export function isJSDocAllType(node: Node): node is JSDocAllType { + return node && node.kind === SyntaxKind.JSDocAllType; + } + export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { + return node && node.kind === SyntaxKind.JSDocUnknownType; + } + export function isJSDocArrayType(node: Node): node is JSDocArrayType { + return node && node.kind === SyntaxKind.JSDocArrayType; + } + export function isJSDocUnionType(node: Node): node is JSDocUnionType { + return node && node.kind === SyntaxKind.JSDocUnionType; + } + export function isJSDocTupleType(node: Node): node is JSDocTupleType { + return node && node.kind === SyntaxKind.JSDocTupleType; + } + export function isJSDocNullableType(node: Node): node is JSDocNullableType { + return node && node.kind === SyntaxKind.JSDocNullableType; + } + export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { + return node && node.kind === SyntaxKind.JSDocNonNullableType; + } + export function isJSDocRecordType(node: Node): node is JSDocRecordType { + return node && node.kind === SyntaxKind.JSDocRecordType; + } + export function isJSDocRecordMember(node: Node): node is JSDocRecordMember { + return node && node.kind === SyntaxKind.JSDocRecordMember; + } + export function isJSDocTypeReference(node: Node): node is JSDocTypeReference { + return node && node.kind === SyntaxKind.JSDocTypeReference; + } + export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { + return node && node.kind === SyntaxKind.JSDocOptionalType; + } + export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { + return node && node.kind === SyntaxKind.JSDocFunctionType; + } + export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { + return node && node.kind === SyntaxKind.JSDocVariadicType; + } + export function isJSDocConstructorType(node: Node): node is JSDocConstructorType { + return node && node.kind === SyntaxKind.JSDocConstructorType; + } + export function isJSDocThisType(node: Node): node is JSDocThisType { + return node && node.kind === SyntaxKind.JSDocThisType; + } + export function isJSDocComment(node: Node): node is JSDocComment { + return node && node.kind === SyntaxKind.JSDocComment; + } + export function isJSDocTag(node: Node): node is JSDocTag { + return node && node.kind === SyntaxKind.JSDocTag; + } + export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { + return node && node.kind === SyntaxKind.JSDocParameterTag; + } + export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { + return node && node.kind === SyntaxKind.JSDocReturnTag; + } + export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { + return node && node.kind === SyntaxKind.JSDocTypeTag; + } + export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { + return node && node.kind === SyntaxKind.JSDocTemplateTag; + } + export function isRawExpression(node: Node): node is RawExpression { + return node && node.kind === SyntaxKind.RawExpression; + } + export function isRawStatement(node: Node): node is RawStatement { + return node && node.kind === SyntaxKind.RawStatement; + } + export function isLiteralExpression(node: Node): node is LiteralExpression { + if (node) { + switch (node.kind) { + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + return true; + } + } + return false; + } + export function isModifier(node: Node): node is Modifier { + if (node) { + switch (node.kind) { + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + return true; + } + } + return false; + } + export function isEntityName(node: Node): node is EntityName { + if (node) { + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + return true; + } + } + return false; + } + export function isDeclarationNameNode(node: Node): node is DeclarationName { + if (node) { + switch (node.kind) { + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + return true; + } + } + return false; + } + export function isPropertyName(node: Node): node is PropertyName { + if (node) { + switch (node.kind) { + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + return true; + } + } + return false; + } + export function isStatementNode(node: Node): node is Statement { + if (node) { + switch (node.kind) { + case SyntaxKind.EmptyStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MissingDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.Block: + case SyntaxKind.RawStatement: + case SyntaxKind.ModuleBlock: + case SyntaxKind.VariableStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.ImportDeclaration: + return true; + } + } + return false; + } + export function isUnaryExpression(node: Node): node is UnaryExpression { + if (node) { + switch (node.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + return true; + } + } + return false; + } + export function isTypeNodeNode(node: Node): node is TypeNode { + if (node) { + switch (node.kind) { + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeReference: + case SyntaxKind.TypePredicate: + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocRecordType: + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.StringLiteral: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + case SyntaxKind.JSDocArrayType: + case SyntaxKind.JSDocUnionType: + case SyntaxKind.JSDocTupleType: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocTypeReference: + case SyntaxKind.JSDocOptionalType: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocVariadicType: + case SyntaxKind.JSDocConstructorType: + case SyntaxKind.JSDocThisType: + return true; + } + } + return false; + } + export function isTypeElement(node: Node): node is TypeElement { + if (node) { + switch (node.kind) { + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.PropertySignature: + case SyntaxKind.JSDocRecordMember: + case SyntaxKind.MethodSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.MissingDeclaration: + return true; + } + } + return false; + } + export function isBindingPatternOrIdentifier(node: Node): node is BindingPattern | Identifier { + if (node) { + switch (node.kind) { + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.Identifier: + return true; + } + } + return false; + } + export function isClassElement(node: Node): node is ClassElement { + if (node) { + switch (node.kind) { + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.SemicolonClassElement: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.IndexSignature: + case SyntaxKind.MissingDeclaration: + return true; + } + } + return false; + } + export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { + if (node) { + switch (node.kind) { + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MissingDeclaration: + return true; + } + } + return false; + } + export function isFunctionBody(node: Node): node is FunctionBody { + if (node) { + switch (node.kind) { + case SyntaxKind.Block: + return true; + } + } + return false; + } + export function isExpressionNode(node: Node): node is Expression { + if (node) { + switch (node.kind) { + case SyntaxKind.OmittedExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.ClassExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + return true; + } + } + return false; + } + export function isConciseBody(node: Node): node is ConciseBody { + if (node) { + switch (node.kind) { + case SyntaxKind.OmittedExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.ClassExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.Block: + return true; + } + } + return false; + } + export function isLiteralExpressionOrTemplateExpression(node: Node): node is LiteralExpression | TemplateExpression { + if (node) { + switch (node.kind) { + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + case SyntaxKind.TemplateExpression: + return true; + } + } + return false; + } + export function isJsxAttributeOrJsxSpreadAttribute(node: Node): node is JsxAttribute | JsxSpreadAttribute { + if (node) { + switch (node.kind) { + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + return true; + } + } + return false; + } + export function isJsxChild(node: Node): node is JsxChild { + if (node) { + switch (node.kind) { + case SyntaxKind.JsxElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxText: + return true; + } + } + return false; + } + export function isExpressionOrVariableDeclarationList(node: Node): node is Expression | VariableDeclarationList { + if (node) { + switch (node.kind) { + case SyntaxKind.OmittedExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.ClassExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.VariableDeclarationList: + return true; + } + } + return false; + } + export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { + if (node) { + switch (node.kind) { + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + return true; + } + } + return false; + } + export function isIdentifierOrLiteralExpression(node: Node): node is Identifier | LiteralExpression { + if (node) { + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.NumericLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.StringLiteral: + case SyntaxKind.RawExpression: + return true; + } + } + return false; + } + export function isModuleBody(node: Node): node is ModuleBody { + if (node) { + switch (node.kind) { + case SyntaxKind.ModuleBlock: + case SyntaxKind.ModuleDeclaration: + return true; + } + } + return false; + } + export function isEntityNameOrExternalModuleReference(node: Node): node is EntityName | ExternalModuleReference { + if (node) { + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + case SyntaxKind.ExternalModuleReference: + return true; + } + } + return false; + } + export function isNamedImportsOrNamespaceImport(node: Node): node is NamedImports | NamespaceImport { + if (node) { + switch (node.kind) { + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + case SyntaxKind.NamespaceImport: + return true; + } + } + return false; + } + export function isImportOrExportSpecifier(node: Node): node is ImportOrExportSpecifier { + if (node) { + switch (node.kind) { + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return true; + } + } + return false; + } + export function isJSDocType(node: Node): node is JSDocType { + if (node) { + switch (node.kind) { + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + case SyntaxKind.JSDocArrayType: + case SyntaxKind.JSDocUnionType: + case SyntaxKind.JSDocTupleType: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocRecordType: + case SyntaxKind.JSDocTypeReference: + case SyntaxKind.JSDocOptionalType: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocVariadicType: + case SyntaxKind.JSDocConstructorType: + case SyntaxKind.JSDocThisType: + return true; + } + } + return false; + } + export function cloneNode(node: TNode, location?: TextRange, flags?: NodeFlags): TNode; + export function cloneNode(node: Node, location?: TextRange, flags: NodeFlags = node.flags): Node { + if (node) { + switch (node.kind) { + case SyntaxKind.NumericLiteral: + return createNumericLiteral((node).text, location, flags); + case SyntaxKind.StringLiteral: + return createStringLiteral((node).text, location, flags); + case SyntaxKind.RegularExpressionLiteral: + return createRegularExpressionLiteral((node).text, location, flags); + case SyntaxKind.NoSubstitutionTemplateLiteral: + return createNoSubstitutionTemplateLiteral((node).text, location, flags); + case SyntaxKind.TemplateHead: + return createTemplateHead((node).text, location, flags); + case SyntaxKind.TemplateMiddle: + return createTemplateMiddle((node).text, location, flags); + case SyntaxKind.TemplateTail: + return createTemplateTail((node).text, location, flags); + case SyntaxKind.Identifier: + return createIdentifier((node).text, (node).originalKeywordKind, location, flags); + case SyntaxKind.FalseKeyword: + return createFalseKeyword(location, flags); + case SyntaxKind.NullKeyword: + return createNullKeyword(location, flags); + case SyntaxKind.SuperKeyword: + return createSuperKeyword(location, flags); + case SyntaxKind.ThisKeyword: + return createThisKeyword(location, flags); + case SyntaxKind.TrueKeyword: + return createTrueKeyword(location, flags); + case SyntaxKind.QualifiedName: + return createQualifiedName((node).left, (node).right, location, flags); + case SyntaxKind.ComputedPropertyName: + return createComputedPropertyName((node).expression, location, flags); + case SyntaxKind.TypeParameter: + return createTypeParameter((node).name, (node).constraint, (node).expression, location, flags); + case SyntaxKind.Parameter: + return createParameter((node).decorators, (node).modifiers, (node).dotDotDotToken, (node).name, (node).questionToken, (node).type, (node).initializer, location, flags); + case SyntaxKind.Decorator: + return createDecorator((node).expression, location, flags); + case SyntaxKind.PropertySignature: + return createPropertySignature((node).decorators, (node).modifiers, (node).name, (node).questionToken, (node).type, location, flags); + case SyntaxKind.PropertyDeclaration: + return createPropertyDeclaration((node).decorators, (node).modifiers, (node).name, (node).type, (node).initializer, location, flags); + case SyntaxKind.MethodSignature: + return createMethodSignature((node).decorators, (node).modifiers, (node).name, (node).questionToken, (node).typeParameters, (node).parameters, (node).type, location, flags); + case SyntaxKind.MethodDeclaration: + return createMethodDeclaration((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.Constructor: + return createConstructor((node).decorators, (node).modifiers, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.GetAccessor: + return createGetAccessor((node).decorators, (node).modifiers, (node).name, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.SetAccessor: + return createSetAccessor((node).decorators, (node).modifiers, (node).name, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.CallSignature: + return createCallSignature((node).typeParameters, (node).parameters, (node).type, (node).questionToken, location, flags); + case SyntaxKind.ConstructSignature: + return createConstructSignature((node).typeParameters, (node).parameters, (node).type, (node).questionToken, location, flags); + case SyntaxKind.IndexSignature: + return createIndexSignature((node).decorators, (node).modifiers, (node).parameters, (node).type, (node).questionToken, location, flags); + case SyntaxKind.TypePredicate: + return createTypePredicate((node).parameterName, (node).type, location, flags); + case SyntaxKind.TypeReference: + return createTypeReference((node).typeName, (node).typeArguments, location, flags); + case SyntaxKind.FunctionType: + return createFunctionType((node).typeParameters, (node).parameters, (node).type, location, flags); + case SyntaxKind.ConstructorType: + return createConstructorType((node).typeParameters, (node).parameters, (node).type, location, flags); + case SyntaxKind.TypeQuery: + return createTypeQuery((node).exprName, location, flags); + case SyntaxKind.TypeLiteral: + return createTypeLiteral((node).members, location, flags); + case SyntaxKind.ArrayType: + return createArrayType((node).elementType, location, flags); + case SyntaxKind.TupleType: + return createTupleType((node).elementTypes, location, flags); + case SyntaxKind.UnionType: + return createUnionType((node).types, location, flags); + case SyntaxKind.IntersectionType: + return createIntersectionType((node).types, location, flags); + case SyntaxKind.ParenthesizedType: + return createParenthesizedType((node).type, location, flags); + case SyntaxKind.ObjectBindingPattern: + return createObjectBindingPattern((node).elements, location, flags); + case SyntaxKind.ArrayBindingPattern: + return createArrayBindingPattern((node).elements, location, flags); + case SyntaxKind.BindingElement: + return createBindingElement((node).propertyName, (node).dotDotDotToken, (node).name, (node).initializer, location, flags); + case SyntaxKind.ArrayLiteralExpression: + return createArrayLiteralExpression((node).elements, location, flags); + case SyntaxKind.ObjectLiteralExpression: + return createObjectLiteralExpression((node).properties, location, flags); + case SyntaxKind.PropertyAccessExpression: + return createPropertyAccessExpression((node).expression, (node).dotToken, (node).name, location, flags); + case SyntaxKind.ElementAccessExpression: + return createElementAccessExpression((node).expression, (node).argumentExpression, location, flags); + case SyntaxKind.CallExpression: + return createCallExpression((node).expression, (node).typeArguments, (node).arguments, location, flags); + case SyntaxKind.NewExpression: + return createNewExpression((node).expression, (node).typeArguments, (node).arguments, location, flags); + case SyntaxKind.TaggedTemplateExpression: + return createTaggedTemplateExpression((node).tag, (node).template, location, flags); + case SyntaxKind.TypeAssertionExpression: + return createTypeAssertionExpression((node).type, (node).expression, location, flags); + case SyntaxKind.ParenthesizedExpression: + return createParenthesizedExpression((node).expression, location, flags); + case SyntaxKind.FunctionExpression: + return createFunctionExpression((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.ArrowFunction: + return createArrowFunction((node).decorators, (node).modifiers, (node).typeParameters, (node).parameters, (node).type, (node).equalsGreaterThanToken, (node).body, location, flags); + case SyntaxKind.DeleteExpression: + return createDeleteExpression((node).expression, location, flags); + case SyntaxKind.TypeOfExpression: + return createTypeOfExpression((node).expression, location, flags); + case SyntaxKind.VoidExpression: + return createVoidExpression((node).expression, location, flags); + case SyntaxKind.AwaitExpression: + return createAwaitExpression((node).expression, location, flags); + case SyntaxKind.PrefixUnaryExpression: + return createPrefixUnaryExpression((node).operator, (node).operand, location, flags); + case SyntaxKind.PostfixUnaryExpression: + return createPostfixUnaryExpression((node).operand, (node).operator, location, flags); + case SyntaxKind.BinaryExpression: + return createBinaryExpression((node).left, (node).operatorToken, (node).right, location, flags); + case SyntaxKind.ConditionalExpression: + return createConditionalExpression((node).condition, (node).questionToken, (node).whenTrue, (node).colonToken, (node).whenFalse, location, flags); + case SyntaxKind.TemplateExpression: + return createTemplateExpression((node).head, (node).templateSpans, location, flags); + case SyntaxKind.YieldExpression: + return createYieldExpression((node).asteriskToken, (node).expression, location, flags); + case SyntaxKind.SpreadElementExpression: + return createSpreadElementExpression((node).expression, location, flags); + case SyntaxKind.ClassExpression: + return createClassExpression((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); + case SyntaxKind.OmittedExpression: + return createOmittedExpression(location, flags); + case SyntaxKind.ExpressionWithTypeArguments: + return createExpressionWithTypeArguments((node).expression, (node).typeArguments, location, flags); + case SyntaxKind.AsExpression: + return createAsExpression((node).expression, (node).type, location, flags); + case SyntaxKind.TemplateSpan: + return createTemplateSpan((node).expression, (node).literal, location, flags); + case SyntaxKind.SemicolonClassElement: + return createSemicolonClassElement(location, flags); + case SyntaxKind.Block: + return createBlock((node).statements, location, flags); + case SyntaxKind.VariableStatement: + return createVariableStatement((node).decorators, (node).modifiers, (node).declarationList, location, flags); + case SyntaxKind.EmptyStatement: + return createEmptyStatement(location, flags); + case SyntaxKind.ExpressionStatement: + return createExpressionStatement((node).expression, location, flags); + case SyntaxKind.IfStatement: + return createIfStatement((node).expression, (node).thenStatement, (node).elseStatement, location, flags); + case SyntaxKind.DoStatement: + return createDoStatement((node).statement, (node).expression, location, flags); + case SyntaxKind.WhileStatement: + return createWhileStatement((node).expression, (node).statement, location, flags); + case SyntaxKind.ForStatement: + return createForStatement((node).initializer, (node).condition, (node).incrementor, (node).statement, location, flags); + case SyntaxKind.ForInStatement: + return createForInStatement((node).initializer, (node).expression, (node).statement, location, flags); + case SyntaxKind.ForOfStatement: + return createForOfStatement((node).initializer, (node).expression, (node).statement, location, flags); + case SyntaxKind.ContinueStatement: + return createContinueStatement((node).label, location, flags); + case SyntaxKind.BreakStatement: + return createBreakStatement((node).label, location, flags); + case SyntaxKind.ReturnStatement: + return createReturnStatement((node).expression, location, flags); + case SyntaxKind.WithStatement: + return createWithStatement((node).expression, (node).statement, location, flags); + case SyntaxKind.SwitchStatement: + return createSwitchStatement((node).expression, (node).caseBlock, location, flags); + case SyntaxKind.LabeledStatement: + return createLabeledStatement((node).label, (node).statement, location, flags); + case SyntaxKind.ThrowStatement: + return createThrowStatement((node).expression, location, flags); + case SyntaxKind.TryStatement: + return createTryStatement((node).tryBlock, (node).catchClause, (node).finallyBlock, location, flags); + case SyntaxKind.DebuggerStatement: + return createDebuggerStatement(location, flags); + case SyntaxKind.VariableDeclaration: + return createVariableDeclaration((node).name, (node).type, (node).initializer, location, flags); + case SyntaxKind.VariableDeclarationList: + return createVariableDeclarationList((node).declarations, location, flags); + case SyntaxKind.FunctionDeclaration: + return createFunctionDeclaration((node).decorators, (node).modifiers, (node).asteriskToken, (node).name, (node).typeParameters, (node).parameters, (node).type, (node).body, location, flags); + case SyntaxKind.ClassDeclaration: + return createClassDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); + case SyntaxKind.InterfaceDeclaration: + return createInterfaceDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).heritageClauses, (node).members, location, flags); + case SyntaxKind.TypeAliasDeclaration: + return createTypeAliasDeclaration((node).decorators, (node).modifiers, (node).name, (node).typeParameters, (node).type, location, flags); + case SyntaxKind.EnumDeclaration: + return createEnumDeclaration((node).decorators, (node).modifiers, (node).name, (node).members, location, flags); + case SyntaxKind.ModuleDeclaration: + return createModuleDeclaration((node).decorators, (node).modifiers, (node).name, (node).body, location, flags); + case SyntaxKind.ModuleBlock: + return createModuleBlock((node).statements, location, flags); + case SyntaxKind.CaseBlock: + return createCaseBlock((node).clauses, location, flags); + case SyntaxKind.ImportEqualsDeclaration: + return createImportEqualsDeclaration((node).decorators, (node).modifiers, (node).name, (node).moduleReference, location, flags); + case SyntaxKind.ImportDeclaration: + return createImportDeclaration((node).decorators, (node).modifiers, (node).importClause, (node).moduleSpecifier, location, flags); + case SyntaxKind.ImportClause: + return createImportClause((node).name, (node).namedBindings, location, flags); + case SyntaxKind.NamespaceImport: + return createNamespaceImport((node).name, location, flags); + case SyntaxKind.NamedImports: + return createNamedImports((node).elements, location, flags); + case SyntaxKind.ImportSpecifier: + return createImportSpecifier((node).propertyName, (node).name, location, flags); + case SyntaxKind.ExportAssignment: + return createExportAssignment((node).decorators, (node).modifiers, (node).expression, location, flags); + case SyntaxKind.ExportDeclaration: + return createExportDeclaration((node).decorators, (node).modifiers, (node).exportClause, (node).moduleSpecifier, location, flags); + case SyntaxKind.NamedExports: + return createNamedExports((node).elements, location, flags); + case SyntaxKind.ExportSpecifier: + return createExportSpecifier((node).propertyName, (node).name, location, flags); + case SyntaxKind.MissingDeclaration: + return createMissingDeclaration((node).decorators, (node).modifiers, (node).questionToken, location, flags); + case SyntaxKind.ExternalModuleReference: + return createExternalModuleReference((node).expression, location, flags); + case SyntaxKind.JsxElement: + return createJsxElement((node).openingElement, (node).children, (node).closingElement, location, flags); + case SyntaxKind.JsxSelfClosingElement: + return createJsxSelfClosingElement((node).tagName, (node).attributes, location, flags); + case SyntaxKind.JsxOpeningElement: + return createJsxOpeningElement((node).tagName, (node).attributes, location, flags); + case SyntaxKind.JsxText: + return createJsxText(location, flags); + case SyntaxKind.JsxClosingElement: + return createJsxClosingElement((node).tagName, location, flags); + case SyntaxKind.JsxAttribute: + return createJsxAttribute((node).name, (node).initializer, location, flags); + case SyntaxKind.JsxSpreadAttribute: + return createJsxSpreadAttribute((node).expression, location, flags); + case SyntaxKind.JsxExpression: + return createJsxExpression((node).expression, location, flags); + case SyntaxKind.CaseClause: + return createCaseClause((node).expression, (node).statements, location, flags); + case SyntaxKind.DefaultClause: + return createDefaultClause((node).statements, location, flags); + case SyntaxKind.HeritageClause: + return createHeritageClause((node).token, (node).types, location, flags); + case SyntaxKind.CatchClause: + return createCatchClause((node).variableDeclaration, (node).block, location, flags); + case SyntaxKind.PropertyAssignment: + return createPropertyAssignment((node).name, (node).initializer, location, flags); + case SyntaxKind.ShorthandPropertyAssignment: + return createShorthandPropertyAssignment((node).name, location, flags); + case SyntaxKind.EnumMember: + return createEnumMember((node).name, (node).initializer, location, flags); + case SyntaxKind.SourceFile: + return createSourceFileNode((node).statements, (node).endOfFileToken, (node).fileName, (node).text, (node).amdDependencies, (node).moduleName, (node).referencedFiles, (node).languageVariant, (node).renamedDependencies, (node).hasNoDefaultLib, (node).languageVersion, (node).externalModuleIndicator, (node).isDefaultLib, (node).identifiers, (node).parseDiagnostics, (node).bindDiagnostics, (node).lineMap, (node).classifiableNames, (node).resolvedModules, (node).imports, location, flags); + case SyntaxKind.JSDocTypeExpression: + return createJSDocTypeExpression((node).type, location, flags); + case SyntaxKind.JSDocAllType: + return createJSDocAllType(location, flags); + case SyntaxKind.JSDocUnknownType: + return createJSDocUnknownType(location, flags); + case SyntaxKind.JSDocArrayType: + return createJSDocArrayType((node).elementType, location, flags); + case SyntaxKind.JSDocUnionType: + return createJSDocUnionType((node).types, location, flags); + case SyntaxKind.JSDocTupleType: + return createJSDocTupleType((node).types, location, flags); + case SyntaxKind.JSDocNullableType: + return createJSDocNullableType((node).type, location, flags); + case SyntaxKind.JSDocNonNullableType: + return createJSDocNonNullableType((node).type, location, flags); + case SyntaxKind.JSDocRecordType: + return createJSDocRecordType((node).members, location, flags); + case SyntaxKind.JSDocRecordMember: + return createJSDocRecordMember((node).name, (node).type, location, flags); + case SyntaxKind.JSDocTypeReference: + return createJSDocTypeReference((node).name, (node).typeArguments, location, flags); + case SyntaxKind.JSDocOptionalType: + return createJSDocOptionalType((node).type, location, flags); + case SyntaxKind.JSDocFunctionType: + return createJSDocFunctionType((node).parameters, (node).type, location, flags); + case SyntaxKind.JSDocVariadicType: + return createJSDocVariadicType((node).type, location, flags); + case SyntaxKind.JSDocConstructorType: + return createJSDocConstructorType((node).type, location, flags); + case SyntaxKind.JSDocThisType: + return createJSDocThisType((node).type, location, flags); + case SyntaxKind.JSDocComment: + return createJSDocComment((node).tags, location, flags); + case SyntaxKind.JSDocTag: + return createJSDocTag((node).atToken, (node).tagName, location, flags); + case SyntaxKind.JSDocParameterTag: + return createJSDocParameterTag((node).preParameterName, (node).typeExpression, (node).postParameterName, (node).atToken, (node).tagName, location, flags); + case SyntaxKind.JSDocReturnTag: + return createJSDocReturnTag((node).typeExpression, (node).atToken, (node).tagName, location, flags); + case SyntaxKind.JSDocTypeTag: + return createJSDocTypeTag((node).typeExpression, (node).atToken, (node).tagName, location, flags); + case SyntaxKind.JSDocTemplateTag: + return createJSDocTemplateTag((node).typeParameters, (node).atToken, (node).tagName, location, flags); + case SyntaxKind.RawExpression: + return createRawExpression((node).text, location, flags); + case SyntaxKind.RawStatement: + return createRawStatement((node).text, location, flags); + } + } + return node; + } + export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node { + if (node) { + switch (node.kind) { + case SyntaxKind.QualifiedName: + return updateQualifiedName(node, (node).left, (node).right); + case SyntaxKind.ComputedPropertyName: + return updateComputedPropertyName(node, (node).expression); + case SyntaxKind.TypeParameter: + return updateTypeParameter(node, (node).name, (node).constraint, (node).expression); + case SyntaxKind.Parameter: + return updateParameter(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, (node).questionToken, (node).type, (node).initializer); + case SyntaxKind.Decorator: + return updateDecorator(node, (node).expression); + case SyntaxKind.PropertySignature: + return updatePropertySignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, (node).type); + case SyntaxKind.PropertyDeclaration: + return updatePropertyDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, (node).type, (node).initializer); + case SyntaxKind.MethodSignature: + return updateMethodSignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.MethodDeclaration: + return updateMethodDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.Constructor: + return updateConstructor(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.GetAccessor: + return updateGetAccessor(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.SetAccessor: + return updateSetAccessor(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.CallSignature: + return updateCallSignature(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.ConstructSignature: + return updateConstructSignature(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.IndexSignature: + return updateIndexSignature(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.TypePredicate: + return updateTypePredicate(node, (node).parameterName, (node).type); + case SyntaxKind.TypeReference: + return updateTypeReference(node, (node).typeName, transformer.visitNodes((node).typeArguments, visitor, isTypeNodeNode)); + case SyntaxKind.FunctionType: + return updateFunctionType(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.ConstructorType: + return updateConstructorType(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.TypeQuery: + return updateTypeQuery(node, (node).exprName); + case SyntaxKind.TypeLiteral: + return updateTypeLiteral(node, transformer.visitNodes((node).members, visitor, isTypeElement)); + case SyntaxKind.ArrayType: + return updateArrayType(node, (node).elementType); + case SyntaxKind.TupleType: + return updateTupleType(node, transformer.visitNodes((node).elementTypes, visitor, isTypeNodeNode)); + case SyntaxKind.UnionType: + return updateUnionType(node, transformer.visitNodes((node).types, visitor, isTypeNodeNode)); + case SyntaxKind.IntersectionType: + return updateIntersectionType(node, transformer.visitNodes((node).types, visitor, isTypeNodeNode)); + case SyntaxKind.ParenthesizedType: + return updateParenthesizedType(node, (node).type); + case SyntaxKind.ObjectBindingPattern: + return updateObjectBindingPattern(node, transformer.visitNodes((node).elements, visitor, isBindingElement)); + case SyntaxKind.ArrayBindingPattern: + return updateArrayBindingPattern(node, transformer.visitNodes((node).elements, visitor, isBindingElement)); + case SyntaxKind.BindingElement: + return updateBindingElement(node, (node).propertyName, (node).name, (node).initializer); + case SyntaxKind.ArrayLiteralExpression: + return updateArrayLiteralExpression(node, transformer.visitNodes((node).elements, visitor, isExpressionNode)); + case SyntaxKind.ObjectLiteralExpression: + return updateObjectLiteralExpression(node, transformer.visitNodes((node).properties, visitor, isObjectLiteralElement)); + case SyntaxKind.PropertyAccessExpression: + return updatePropertyAccessExpression(node, (node).expression, (node).name); + case SyntaxKind.ElementAccessExpression: + return updateElementAccessExpression(node, (node).expression, (node).argumentExpression); + case SyntaxKind.CallExpression: + return updateCallExpression(node, (node).expression, transformer.visitNodes((node).typeArguments, visitor, isTypeNodeNode), transformer.visitNodes((node).arguments, visitor, isExpressionNode)); + case SyntaxKind.NewExpression: + return updateNewExpression(node, (node).expression, transformer.visitNodes((node).typeArguments, visitor, isTypeNodeNode), transformer.visitNodes((node).arguments, visitor, isExpressionNode)); + case SyntaxKind.TaggedTemplateExpression: + return updateTaggedTemplateExpression(node, (node).tag, (node).template); + case SyntaxKind.TypeAssertionExpression: + return updateTypeAssertionExpression(node, (node).type, (node).expression); + case SyntaxKind.ParenthesizedExpression: + return updateParenthesizedExpression(node, (node).expression); + case SyntaxKind.FunctionExpression: + return updateFunctionExpression(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.ArrowFunction: + return updateArrowFunction(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.DeleteExpression: + return updateDeleteExpression(node, (node).expression); + case SyntaxKind.TypeOfExpression: + return updateTypeOfExpression(node, (node).expression); + case SyntaxKind.VoidExpression: + return updateVoidExpression(node, (node).expression); + case SyntaxKind.AwaitExpression: + return updateAwaitExpression(node, (node).expression); + case SyntaxKind.PrefixUnaryExpression: + return updatePrefixUnaryExpression(node, (node).operand); + case SyntaxKind.PostfixUnaryExpression: + return updatePostfixUnaryExpression(node, (node).operand); + case SyntaxKind.BinaryExpression: + return updateBinaryExpression(node, (node).left, (node).right); + case SyntaxKind.ConditionalExpression: + return updateConditionalExpression(node, (node).condition, (node).whenTrue, (node).whenFalse); + case SyntaxKind.TemplateExpression: + return updateTemplateExpression(node, (node).head, transformer.visitNodes((node).templateSpans, visitor, isTemplateSpan)); + case SyntaxKind.YieldExpression: + return updateYieldExpression(node, (node).expression); + case SyntaxKind.SpreadElementExpression: + return updateSpreadElementExpression(node, (node).expression); + case SyntaxKind.ClassExpression: + return updateClassExpression(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).heritageClauses, visitor, isHeritageClause), transformer.visitNodes((node).members, visitor, isClassElement)); + case SyntaxKind.ExpressionWithTypeArguments: + return updateExpressionWithTypeArguments(node, (node).expression, transformer.visitNodes((node).typeArguments, visitor, isTypeNodeNode)); + case SyntaxKind.AsExpression: + return updateAsExpression(node, (node).expression, (node).type); + case SyntaxKind.TemplateSpan: + return updateTemplateSpan(node, (node).expression, (node).literal); + case SyntaxKind.Block: + return updateBlock(node, transformer.visitNodes((node).statements, visitor, isStatementNode)); + case SyntaxKind.VariableStatement: + return updateVariableStatement(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).declarationList); + case SyntaxKind.ExpressionStatement: + return updateExpressionStatement(node, (node).expression); + case SyntaxKind.IfStatement: + return updateIfStatement(node, (node).expression, (node).thenStatement, (node).elseStatement); + case SyntaxKind.DoStatement: + return updateDoStatement(node, (node).statement, (node).expression); + case SyntaxKind.WhileStatement: + return updateWhileStatement(node, (node).expression, (node).statement); + case SyntaxKind.ForStatement: + return updateForStatement(node, (node).initializer, (node).condition, (node).incrementor, (node).statement); + case SyntaxKind.ForInStatement: + return updateForInStatement(node, (node).initializer, (node).expression, (node).statement); + case SyntaxKind.ForOfStatement: + return updateForOfStatement(node, (node).initializer, (node).expression, (node).statement); + case SyntaxKind.ContinueStatement: + return updateContinueStatement(node, (node).label); + case SyntaxKind.BreakStatement: + return updateBreakStatement(node, (node).label); + case SyntaxKind.ReturnStatement: + return updateReturnStatement(node, (node).expression); + case SyntaxKind.WithStatement: + return updateWithStatement(node, (node).expression, (node).statement); + case SyntaxKind.SwitchStatement: + return updateSwitchStatement(node, (node).expression, (node).caseBlock); + case SyntaxKind.LabeledStatement: + return updateLabeledStatement(node, (node).label, (node).statement); + case SyntaxKind.ThrowStatement: + return updateThrowStatement(node, (node).expression); + case SyntaxKind.TryStatement: + return updateTryStatement(node, (node).tryBlock, (node).catchClause, (node).finallyBlock); + case SyntaxKind.VariableDeclaration: + return updateVariableDeclaration(node, (node).name, (node).type, (node).initializer); + case SyntaxKind.VariableDeclarationList: + return updateVariableDeclarationList(node, transformer.visitNodes((node).declarations, visitor, isVariableDeclaration)); + case SyntaxKind.FunctionDeclaration: + return updateFunctionDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).parameters, visitor, isParameter), (node).type, (node).body); + case SyntaxKind.ClassDeclaration: + return updateClassDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).heritageClauses, visitor, isHeritageClause), transformer.visitNodes((node).members, visitor, isClassElement)); + case SyntaxKind.InterfaceDeclaration: + return updateInterfaceDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), transformer.visitNodes((node).heritageClauses, visitor, isHeritageClause), transformer.visitNodes((node).members, visitor, isTypeElement)); + case SyntaxKind.TypeAliasDeclaration: + return updateTypeAliasDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), (node).type); + case SyntaxKind.EnumDeclaration: + return updateEnumDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, transformer.visitNodes((node).members, visitor, isEnumMember)); + case SyntaxKind.ModuleDeclaration: + return updateModuleDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, (node).body); + case SyntaxKind.ModuleBlock: + return updateModuleBlock(node, transformer.visitNodes((node).statements, visitor, isStatementNode)); + case SyntaxKind.CaseBlock: + return updateCaseBlock(node, transformer.visitNodes((node).clauses, visitor, isCaseOrDefaultClause)); + case SyntaxKind.ImportEqualsDeclaration: + return updateImportEqualsDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).name, (node).moduleReference); + case SyntaxKind.ImportDeclaration: + return updateImportDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).importClause, (node).moduleSpecifier); + case SyntaxKind.ImportClause: + return updateImportClause(node, (node).name, (node).namedBindings); + case SyntaxKind.NamespaceImport: + return updateNamespaceImport(node, (node).name); + case SyntaxKind.NamedImports: + return updateNamedImports(node, transformer.visitNodes((node).elements, visitor, isImportOrExportSpecifier)); + case SyntaxKind.ImportSpecifier: + return updateImportSpecifier(node, (node).propertyName, (node).name); + case SyntaxKind.ExportAssignment: + return updateExportAssignment(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).expression); + case SyntaxKind.ExportDeclaration: + return updateExportDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier), (node).exportClause, (node).moduleSpecifier); + case SyntaxKind.NamedExports: + return updateNamedExports(node, transformer.visitNodes((node).elements, visitor, isImportOrExportSpecifier)); + case SyntaxKind.ExportSpecifier: + return updateExportSpecifier(node, (node).propertyName, (node).name); + case SyntaxKind.MissingDeclaration: + return updateMissingDeclaration(node, transformer.visitNodes((node).decorators, visitor, isDecorator), transformer.visitNodes((node).modifiers, visitor, isModifier)); + case SyntaxKind.ExternalModuleReference: + return updateExternalModuleReference(node, (node).expression); + case SyntaxKind.JsxElement: + return updateJsxElement(node, (node).openingElement, transformer.visitNodes((node).children, visitor, isJsxChild), (node).closingElement); + case SyntaxKind.JsxSelfClosingElement: + return updateJsxSelfClosingElement(node, (node).tagName, transformer.visitNodes((node).attributes, visitor, isJsxAttributeOrJsxSpreadAttribute)); + case SyntaxKind.JsxOpeningElement: + return updateJsxOpeningElement(node, (node).tagName, transformer.visitNodes((node).attributes, visitor, isJsxAttributeOrJsxSpreadAttribute)); + case SyntaxKind.JsxClosingElement: + return updateJsxClosingElement(node, (node).tagName); + case SyntaxKind.JsxAttribute: + return updateJsxAttribute(node, (node).name, (node).initializer); + case SyntaxKind.JsxSpreadAttribute: + return updateJsxSpreadAttribute(node, (node).expression); + case SyntaxKind.JsxExpression: + return updateJsxExpression(node, (node).expression); + case SyntaxKind.CaseClause: + return updateCaseClause(node, (node).expression, transformer.visitNodes((node).statements, visitor, isStatementNode)); + case SyntaxKind.DefaultClause: + return updateDefaultClause(node, transformer.visitNodes((node).statements, visitor, isStatementNode)); + case SyntaxKind.HeritageClause: + return updateHeritageClause(node, transformer.visitNodes((node).types, visitor, isExpressionWithTypeArguments)); + case SyntaxKind.CatchClause: + return updateCatchClause(node, (node).variableDeclaration, (node).block); + case SyntaxKind.PropertyAssignment: + return updatePropertyAssignment(node, (node).name, (node).initializer); + case SyntaxKind.ShorthandPropertyAssignment: + return updateShorthandPropertyAssignment(node, (node).name); + case SyntaxKind.EnumMember: + return updateEnumMember(node, (node).name, (node).initializer); + case SyntaxKind.SourceFile: + return updateSourceFileNode(node, transformer.visitNodes((node).statements, visitor, isStatementNode), (node).endOfFileToken); + case SyntaxKind.JSDocTypeExpression: + return updateJSDocTypeExpression(node, (node).type); + case SyntaxKind.JSDocArrayType: + return updateJSDocArrayType(node, (node).elementType); + case SyntaxKind.JSDocUnionType: + return updateJSDocUnionType(node, transformer.visitNodes((node).types, visitor, isJSDocType)); + case SyntaxKind.JSDocTupleType: + return updateJSDocTupleType(node, transformer.visitNodes((node).types, visitor, isJSDocType)); + case SyntaxKind.JSDocNullableType: + return updateJSDocNullableType(node, (node).type); + case SyntaxKind.JSDocNonNullableType: + return updateJSDocNonNullableType(node, (node).type); + case SyntaxKind.JSDocRecordType: + return updateJSDocRecordType(node, transformer.visitNodes((node).members, visitor, isJSDocRecordMember)); + case SyntaxKind.JSDocRecordMember: + return updateJSDocRecordMember(node, (node).name, (node).type); + case SyntaxKind.JSDocTypeReference: + return updateJSDocTypeReference(node, (node).name, transformer.visitNodes((node).typeArguments, visitor, isJSDocType)); + case SyntaxKind.JSDocOptionalType: + return updateJSDocOptionalType(node, (node).type); + case SyntaxKind.JSDocFunctionType: + return updateJSDocFunctionType(node, transformer.visitNodes((node).parameters, visitor, isParameter), (node).type); + case SyntaxKind.JSDocVariadicType: + return updateJSDocVariadicType(node, (node).type); + case SyntaxKind.JSDocConstructorType: + return updateJSDocConstructorType(node, (node).type); + case SyntaxKind.JSDocThisType: + return updateJSDocThisType(node, (node).type); + case SyntaxKind.JSDocComment: + return updateJSDocComment(node, transformer.visitNodes((node).tags, visitor, isJSDocTag)); + case SyntaxKind.JSDocTag: + return updateJSDocTag(node, (node).tagName); + case SyntaxKind.JSDocParameterTag: + return updateJSDocParameterTag(node, (node).preParameterName, (node).typeExpression, (node).postParameterName, (node).tagName); + case SyntaxKind.JSDocReturnTag: + return updateJSDocReturnTag(node, (node).typeExpression, (node).tagName); + case SyntaxKind.JSDocTypeTag: + return updateJSDocTypeTag(node, (node).typeExpression, (node).tagName); + case SyntaxKind.JSDocTemplateTag: + return updateJSDocTemplateTag(node, transformer.visitNodes((node).typeParameters, visitor, isTypeParameter), (node).tagName); + } + } + return node; + } +} \ No newline at end of file diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 46f6bbda58a..481be12a860 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -6,7 +6,7 @@ namespace ts { export function getNodeConstructor(kind: SyntaxKind): new () => Node { return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)); } - + export function setNodeFlags(node: T, flags: NodeFlags): T { if (!node || flags === undefined) { return node; @@ -34,7 +34,7 @@ namespace ts { return node; } - + export function setOriginalNode(node: T, original: Node): T { node.original = node; return node; @@ -65,7 +65,8 @@ namespace ts { newNode.original = oldNode; newNode.pos = oldNode.pos; newNode.end = oldNode.end; - + newNode.id = oldNode.id; + //mergeCommentRanges(oldNode, newNode); return newNode; } @@ -101,7 +102,7 @@ namespace ts { nodes.pos = location.pos; nodes.end = location.end; } - else if (nodes.pos === undefined) { + if (nodes.pos === undefined || nodes.end === undefined) { nodes.pos = -1; nodes.end = -1; } @@ -122,22 +123,22 @@ namespace ts { return modifiers; } - + // export function createSourceFileNode(): SourceFile { // let node = createNode(SyntaxKind.SourceFile); // return node; // } - + // export function updateSourceFileNode(node: SourceFile, statements: NodeArray, endOfFileToken: Node): SourceFile { // if (statements !== node.statements || endOfFileToken !== node.endOfFileToken) { // let newNode = createNode(SyntaxKind.SourceFile); // newNode.statements = statements; // newNode.endOfFileToken = endOfFileToken; - // return updateFrom(node, newNode); + // return updateFrom(node, newNode); // } // return node; // } - + export function createNumericLiteral2(value: number, location?: TextRange, flags?: NodeFlags): LiteralExpression { let node = createNumericLiteral(String(value), location, flags); return node; @@ -161,7 +162,7 @@ namespace ts { 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; @@ -174,7 +175,7 @@ namespace ts { return createParenthesizedExpression(expr); } else { - // higher precedence. + // higher precedence. return expr; } } @@ -208,8 +209,8 @@ namespace ts { return createCallExpression(parenthesizeForAccess(expression), undefined, _arguments, location, flags); } - export function createObjectLiteralExpression2(properties?: ObjectLiteralElement[]) { - return createObjectLiteralExpression(undefined, undefined, createNodeArray(properties)); + export function createPropertyAssignment2(name: string, initializer: Expression) { + return createPropertyAssignment(createIdentifier(name), initializer); } export function createAssignmentExpression(left: Expression, right: Expression) { @@ -232,12 +233,24 @@ namespace ts { return createBinaryExpression2(left, SyntaxKind.BarBarToken, right); } + export function createLessThanExpression(left: Expression, right: Expression, location?: TextRange) { + return createBinaryExpression2(left, SyntaxKind.LessThanToken, right, location); + } + + export function createAddExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.PlusToken, right); + } + + export function createSubtractExpression(left: Expression, right: Expression) { + return createBinaryExpression2(left, SyntaxKind.MinusToken, right); + } + export function createCommaExpression(left: Expression, right: Expression) { return createBinaryExpression2(left, SyntaxKind.CommaToken, right); } - export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression) { - return createBinaryExpression(parenthesizeForBinary(left, operator), createNode(operator), parenthesizeForBinary(right, operator)); + export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) { + return createBinaryExpression(parenthesizeForBinary(left, operator), createNode(operator), parenthesizeForBinary(right, operator), location); } export function createConditionalExpression2(condition: Expression, whenTrue: Expression, whenFalse: Expression, location?: TextRange, flags?: NodeFlags) { @@ -248,10 +261,18 @@ namespace ts { return createParameter(undefined, undefined, undefined, name, undefined, undefined, initializer, location, flags); } + export function createParameter3(name: string) { + return createParameter2(createIdentifier(name)); + } + export function createRestParameter(name: Identifier, location?: TextRange, flags?: NodeFlags) { return createParameter(undefined, undefined, createNode(SyntaxKind.DotDotDotToken), name, undefined, undefined, undefined, location, flags); } + export function createVariableDeclarationList2(name: Identifier | BindingPattern, initializer?: Expression) { + return createVariableDeclarationList([createVariableDeclaration2(name, initializer)]); + } + export function createVariableDeclaration2(name: Identifier | BindingPattern, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { return createVariableDeclaration(name, undefined, initializer, location, flags); } @@ -318,7 +339,11 @@ namespace ts { return createFunctionExpression(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags); } - export function createFunctionExpression3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { + export function createFunctionExpression3(parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { + return createFunctionExpression(undefined, undefined, undefined, undefined, undefined, parameters, undefined, body, location, flags); + } + + export function createFunctionExpression4(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { return createFunctionExpression(undefined, undefined, asteriskToken, name, undefined, parameters, undefined, body, location, flags); } @@ -348,8 +373,17 @@ namespace ts { return createElementAccessExpression2(expression, createNumericLiteral2(index), location, flags); } - export function createSliceCall(value: Expression, sliceIndex: number, location?: TextRange, flags?: NodeFlags): CallExpression { - return createCallExpression2(createPropertyAccessExpression3(value, "slice"), [createNumericLiteral2(sliceIndex)], location, flags); + export function createConcatCall(value: Expression, _arguments: Expression[]) { + return createCallExpression2(createPropertyAccessExpression3(value, "concat"), _arguments); + } + + export function createSliceCall(value: Expression, sliceIndex?: number, location?: TextRange, flags?: NodeFlags): CallExpression { + let sliceArguments: Expression[] = typeof sliceIndex === "number" ? [createNumericLiteral2(sliceIndex)] : []; + return createCallExpression2(createPropertyAccessExpression3(value, "slice"), sliceArguments, location, flags); + } + + export function createCallCall(target: Expression, thisArg: Expression, _arguments: Expression[], location?: TextRange, flags?: NodeFlags) { + return createCallExpression2(createPropertyAccessExpression3(target, "call"), [thisArg, ..._arguments], location, flags); } export function createApplyCall(target: Expression, thisArg: Expression, _arguments: Expression, location?: TextRange, flags?: NodeFlags) { @@ -366,7 +400,7 @@ namespace ts { return createCallExpression2(createIdentifier("__awaiter"), [createThisKeyword(), argumentsExpr, promiseExpr, createGeneratorFunctionExpression([], body)]); } - function convertEntityNameToExpression(node: EntityName | Expression): Expression { + export function convertEntityNameToExpression(node: EntityName | Expression): Expression { return isQualifiedName(node) ? createPropertyAccessExpression2(convertEntityNameToExpression(node.left), cloneNode(node.right)) : cloneNode(node); } @@ -382,35 +416,87 @@ namespace ts { return createCallExpression2(createIdentifier("__metadata"), [createStringLiteral(metadataKey), metadataValue]); } - export function createDefinePropertyCall(target: Expression, memberName: Expression, descriptor: Expression) { - return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "defineProperty"), [target, memberName, descriptor]); + export function createDefinePropertyCall(target: Expression, memberName: Expression, descriptor: Expression, location?: TextRange) { + return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "defineProperty"), [target, memberName, descriptor], location); + } + + export function createDefinePropertyCall2(target: Expression, memberName: Expression, getter: Expression, setter: Expression, location?: TextRange) { + let properties: ObjectLiteralElement[] = []; + if (getter) { + let get = createPropertyAssignment2("get", getter); + properties.push(get); + startOnNewLine(get); + } + if (setter) { + let set = createPropertyAssignment2("set", setter) + startOnNewLine(set); + properties.push(set); + } + + let enumerable = createPropertyAssignment2("enumerable", createTrueKeyword()); + startOnNewLine(enumerable); + properties.push(enumerable); + + let configurable = createPropertyAssignment2("configurable", createTrueKeyword()); + startOnNewLine(configurable); + properties.push(configurable); + + let descriptor = createObjectLiteralExpression(properties); + return createDefinePropertyCall(target, memberName, descriptor, location); } export function createGetOwnPropertyDescriptorCall(target: Expression, memberName: Expression) { return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "getOwnPropertyDescriptor"), [target, memberName]); } + export function createReactCreateElementCall(tagName: Expression, props: Expression, children: Expression[]): LeftHandSideExpression { + let args: Expression[] = [tagName]; + if (props) { + args.push(props) + } + if (children && children.length > 0) { + if (!props) { + args.push(createNode(SyntaxKind.NullKeyword)); + } + + args.push(...children); + } + return createCallExpression2(createPropertyAccessExpression3(createIdentifier("React"), "createElement"), args); + } + + export function createReactSpreadCall(segments: Expression[]): LeftHandSideExpression { + return createCallExpression2(createPropertyAccessExpression3(createIdentifier("React"), "__spread"), segments); + } + export function createDefaultValueCheck(value: Expression, defaultValue: Expression, ensureIdentifier: (value: Expression, reuseIdentifierExpressions: boolean) => Expression, location?: TextRange, flags?: NodeFlags): Expression { // The value expression will be evaluated twice, so for anything but a simple identifier // we need to generate a temporary variable value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true); - + // === void 0 ? : return createConditionalExpression2(createStrictEqualityExpression(value, createVoidZeroExpression()), defaultValue, value, location, flags); } export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange, flags?: NodeFlags): MemberExpression { - return isIdentifier(memberName) - ? createPropertyAccessExpression2(target, cloneNode(memberName), location, flags) - : isComputedPropertyName(memberName) - ? createElementAccessExpression2(target, cloneNode(memberName.expression), location, flags) - : createElementAccessExpression2(target, cloneNode(memberName), location, flags); + return isIdentifier(memberName) ? createPropertyAccessExpression2(target, cloneNode(memberName), location, flags) + : isComputedPropertyName(memberName) ? createElementAccessExpression2(target, cloneNode(memberName.expression), location, flags) + : createElementAccessExpression2(target, cloneNode(memberName), location, flags); + } + + export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression { + return isIdentifier(memberName) ? createStringLiteral(memberName.text, location) + : isComputedPropertyName(memberName) ? cloneNode(memberName.expression, location) + : cloneNode(memberName, location); + } + + export function makeFunctionBody(body: ConciseBody): FunctionBody { + return isBlock(body) ? body : createBlock([createReturnStatement(body)]); } export function inlineExpressions(expressions: Expression[]) { return reduceLeft(expressions, createCommaExpression); } - + export function isDeclarationStatement(node: Node): node is DeclarationStatement { if (node) { switch (node.kind) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bc13af18416..062d19caf44 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,4 +1,5 @@ /// +/// /// namespace ts { diff --git a/src/compiler/transform.generated.ts b/src/compiler/transform.generated.ts deleted file mode 100644 index 7686261699d..00000000000 --- a/src/compiler/transform.generated.ts +++ /dev/null @@ -1,569 +0,0 @@ -// -/// -/// -/* @internal */ -namespace ts { - export function accept(transformer: Transformer, node: Node, pipeline: Pipeline, write: PipelineOutput): void { - if (!node) { - return; - } - let { visitNode, visitNodes } = transformer; - switch (node.kind) { - case SyntaxKind.QualifiedName: - return write(updateQualifiedName(node, - visitNode((node).left, pipeline), - visitNode((node).right, pipeline))); - case SyntaxKind.ComputedPropertyName: - return write(updateComputedPropertyName(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.TypeParameter: - return write(updateTypeParameter(node, - visitNode((node).name, pipeline), - visitNode((node).constraint, pipeline), - visitNode((node).expression, pipeline))); - case SyntaxKind.Parameter: - return write(updateParameter(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - (node).questionToken, - visitNode((node).type, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.Decorator: - return write(updateDecorator(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.PropertySignature: - return write(updatePropertySignature(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.PropertyDeclaration: - return write(updatePropertyDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNode((node).type, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.MethodSignature: - return write(updateMethodSignature(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.MethodDeclaration: - return write(updateMethodDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.Constructor: - return write(updateConstructor(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.GetAccessor: - return write(updateGetAccessor(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.SetAccessor: - return write(updateSetAccessor(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.CallSignature: - return write(updateCallSignature(node, - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.ConstructSignature: - return write(updateConstructSignature(node, - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.IndexSignature: - return write(updateIndexSignature(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.TypePredicate: - return write(updateTypePredicate(node, - visitNode((node).parameterName, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.TypeReference: - return write(updateTypeReference(node, - visitNode((node).typeName, pipeline), - visitNodes((node).typeArguments, pipeline))); - case SyntaxKind.FunctionType: - return write(updateFunctionType(node, - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.ConstructorType: - return write(updateConstructorType(node, - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.TypeQuery: - return write(updateTypeQuery(node, - visitNode((node).exprName, pipeline))); - case SyntaxKind.TypeLiteral: - return write(updateTypeLiteral(node, - visitNodes((node).members, pipeline))); - case SyntaxKind.ArrayType: - return write(updateArrayType(node, - visitNode((node).elementType, pipeline))); - case SyntaxKind.TupleType: - return write(updateTupleType(node, - visitNodes((node).elementTypes, pipeline))); - case SyntaxKind.UnionType: - return write(updateUnionType(node, - visitNodes((node).types, pipeline))); - case SyntaxKind.IntersectionType: - return write(updateIntersectionType(node, - visitNodes((node).types, pipeline))); - case SyntaxKind.ParenthesizedType: - return write(updateParenthesizedType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.ObjectBindingPattern: - return write(updateObjectBindingPattern(node, - visitNodes((node).elements, pipeline))); - case SyntaxKind.ArrayBindingPattern: - return write(updateArrayBindingPattern(node, - visitNodes((node).elements, pipeline))); - case SyntaxKind.BindingElement: - return write(updateBindingElement(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).propertyName, pipeline), - visitNode((node).name, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.ArrayLiteralExpression: - return write(updateArrayLiteralExpression(node, - visitNodes((node).elements, pipeline))); - case SyntaxKind.ObjectLiteralExpression: - return write(updateObjectLiteralExpression(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNodes((node).properties, pipeline))); - case SyntaxKind.PropertyAccessExpression: - return write(updatePropertyAccessExpression(node, - visitNode((node).expression, pipeline), - visitNode((node).name, pipeline))); - case SyntaxKind.ElementAccessExpression: - return write(updateElementAccessExpression(node, - visitNode((node).expression, pipeline), - visitNode((node).argumentExpression, pipeline))); - case SyntaxKind.CallExpression: - return write(updateCallExpression(node, - visitNode((node).expression, pipeline), - visitNodes((node).typeArguments, pipeline), - visitNodes((node).arguments, pipeline))); - case SyntaxKind.NewExpression: - return write(updateNewExpression(node, - visitNode((node).expression, pipeline), - visitNodes((node).typeArguments, pipeline), - visitNodes((node).arguments, pipeline))); - case SyntaxKind.TaggedTemplateExpression: - return write(updateTaggedTemplateExpression(node, - visitNode((node).tag, pipeline), - visitNode((node).template, pipeline))); - case SyntaxKind.TypeAssertionExpression: - return write(updateTypeAssertionExpression(node, - visitNode((node).type, pipeline), - visitNode((node).expression, pipeline))); - case SyntaxKind.ParenthesizedExpression: - return write(updateParenthesizedExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.FunctionExpression: - return write(updateFunctionExpression(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.ArrowFunction: - return write(updateArrowFunction(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.DeleteExpression: - return write(updateDeleteExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.TypeOfExpression: - return write(updateTypeOfExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.VoidExpression: - return write(updateVoidExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.AwaitExpression: - return write(updateAwaitExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.PrefixUnaryExpression: - return write(updatePrefixUnaryExpression(node, - visitNode((node).operand, pipeline))); - case SyntaxKind.PostfixUnaryExpression: - return write(updatePostfixUnaryExpression(node, - visitNode((node).operand, pipeline))); - case SyntaxKind.BinaryExpression: - return write(updateBinaryExpression(node, - visitNode((node).left, pipeline), - visitNode((node).right, pipeline))); - case SyntaxKind.ConditionalExpression: - return write(updateConditionalExpression(node, - visitNode((node).condition, pipeline), - visitNode((node).whenTrue, pipeline), - visitNode((node).whenFalse, pipeline))); - case SyntaxKind.TemplateExpression: - return write(updateTemplateExpression(node, - visitNode((node).head, pipeline), - visitNodes((node).templateSpans, pipeline))); - case SyntaxKind.YieldExpression: - return write(updateYieldExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.SpreadElementExpression: - return write(updateSpreadElementExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.ClassExpression: - return write(updateClassExpression(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).heritageClauses, pipeline), - visitNodes((node).members, pipeline))); - case SyntaxKind.ExpressionWithTypeArguments: - return write(updateExpressionWithTypeArguments(node, - visitNode((node).expression, pipeline), - visitNodes((node).typeArguments, pipeline))); - case SyntaxKind.AsExpression: - return write(updateAsExpression(node, - visitNode((node).expression, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.TemplateSpan: - return write(updateTemplateSpan(node, - visitNode((node).expression, pipeline), - visitNode((node).literal, pipeline))); - case SyntaxKind.Block: - return write(updateBlock(node, - visitNodes((node).statements, pipeline))); - case SyntaxKind.VariableStatement: - return write(updateVariableStatement(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).declarationList, pipeline))); - case SyntaxKind.ExpressionStatement: - return write(updateExpressionStatement(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.IfStatement: - return write(updateIfStatement(node, - visitNode((node).expression, pipeline), - visitNode((node).thenStatement, pipeline, PipelineFlags.StatementOrBlock), - visitNode((node).elseStatement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.DoStatement: - return write(updateDoStatement(node, - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock), - visitNode((node).expression, pipeline))); - case SyntaxKind.WhileStatement: - return write(updateWhileStatement(node, - visitNode((node).expression, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.ForStatement: - return write(updateForStatement(node, - visitNode((node).initializer, pipeline), - visitNode((node).condition, pipeline), - visitNode((node).incrementor, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.ForInStatement: - return write(updateForInStatement(node, - visitNode((node).initializer, pipeline), - visitNode((node).expression, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.ForOfStatement: - return write(updateForOfStatement(node, - visitNode((node).initializer, pipeline), - visitNode((node).expression, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.ContinueStatement: - return write(updateContinueStatement(node, - visitNode((node).label, pipeline))); - case SyntaxKind.BreakStatement: - return write(updateBreakStatement(node, - visitNode((node).label, pipeline))); - case SyntaxKind.ReturnStatement: - return write(updateReturnStatement(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.WithStatement: - return write(updateWithStatement(node, - visitNode((node).expression, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.SwitchStatement: - return write(updateSwitchStatement(node, - visitNode((node).expression, pipeline), - visitNode((node).caseBlock, pipeline))); - case SyntaxKind.LabeledStatement: - return write(updateLabeledStatement(node, - visitNode((node).label, pipeline), - visitNode((node).statement, pipeline, PipelineFlags.StatementOrBlock))); - case SyntaxKind.ThrowStatement: - return write(updateThrowStatement(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.TryStatement: - return write(updateTryStatement(node, - visitNode((node).tryBlock, pipeline), - visitNode((node).catchClause, pipeline), - visitNode((node).finallyBlock, pipeline))); - case SyntaxKind.VariableDeclaration: - return write(updateVariableDeclaration(node, - visitNode((node).name, pipeline), - visitNode((node).type, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.VariableDeclarationList: - return write(updateVariableDeclarationList(node, - visitNodes((node).declarations, pipeline))); - case SyntaxKind.FunctionDeclaration: - return write(updateFunctionDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.ClassDeclaration: - return write(updateClassDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).heritageClauses, pipeline), - visitNodes((node).members, pipeline))); - case SyntaxKind.InterfaceDeclaration: - return write(updateInterfaceDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNodes((node).heritageClauses, pipeline), - visitNodes((node).members, pipeline))); - case SyntaxKind.TypeAliasDeclaration: - return write(updateTypeAliasDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).typeParameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.EnumDeclaration: - return write(updateEnumDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNodes((node).members, pipeline))); - case SyntaxKind.ModuleDeclaration: - return write(updateModuleDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNode((node).body, pipeline, PipelineFlags.LexicalEnvironment))); - case SyntaxKind.ModuleBlock: - return write(updateModuleBlock(node, - visitNodes((node).statements, pipeline))); - case SyntaxKind.CaseBlock: - return write(updateCaseBlock(node, - visitNodes((node).clauses, pipeline))); - case SyntaxKind.ImportEqualsDeclaration: - return write(updateImportEqualsDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).name, pipeline), - visitNode((node).moduleReference, pipeline))); - case SyntaxKind.ImportDeclaration: - return write(updateImportDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).importClause, pipeline), - visitNode((node).moduleSpecifier, pipeline))); - case SyntaxKind.ImportClause: - return write(updateImportClause(node, - visitNode((node).name, pipeline), - visitNode((node).namedBindings, pipeline))); - case SyntaxKind.NamespaceImport: - return write(updateNamespaceImport(node, - visitNode((node).name, pipeline))); - case SyntaxKind.NamedImports: - return write(updateNamedImports(node, - visitNodes((node).elements, pipeline))); - case SyntaxKind.ImportSpecifier: - return write(updateImportSpecifier(node, - visitNode((node).propertyName, pipeline), - visitNode((node).name, pipeline))); - case SyntaxKind.ExportAssignment: - return write(updateExportAssignment(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).expression, pipeline))); - case SyntaxKind.ExportDeclaration: - return write(updateExportDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline), - visitNode((node).exportClause, pipeline), - visitNode((node).moduleSpecifier, pipeline))); - case SyntaxKind.NamedExports: - return write(updateNamedExports(node, - visitNodes((node).elements, pipeline))); - case SyntaxKind.ExportSpecifier: - return write(updateExportSpecifier(node, - visitNode((node).propertyName, pipeline), - visitNode((node).name, pipeline))); - case SyntaxKind.MissingDeclaration: - return write(updateMissingDeclaration(node, - visitNodes((node).decorators, pipeline), - visitNodes((node).modifiers, pipeline))); - case SyntaxKind.ExternalModuleReference: - return write(updateExternalModuleReference(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.JsxElement: - return write(updateJsxElement(node, - visitNode((node).openingElement, pipeline), - visitNodes((node).children, pipeline), - visitNode((node).closingElement, pipeline))); - case SyntaxKind.JsxSelfClosingElement: - return write(updateJsxSelfClosingElement(node, - visitNode((node).tagName, pipeline), - visitNodes((node).attributes, pipeline))); - case SyntaxKind.JsxOpeningElement: - return write(updateJsxOpeningElement(node, - visitNode((node).tagName, pipeline), - visitNodes((node).attributes, pipeline))); - case SyntaxKind.JsxClosingElement: - return write(updateJsxClosingElement(node, - visitNode((node).tagName, pipeline))); - case SyntaxKind.JsxAttribute: - return write(updateJsxAttribute(node, - visitNode((node).name, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.JsxSpreadAttribute: - return write(updateJsxSpreadAttribute(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.JsxExpression: - return write(updateJsxExpression(node, - visitNode((node).expression, pipeline))); - case SyntaxKind.CaseClause: - return write(updateCaseClause(node, - visitNode((node).expression, pipeline), - visitNodes((node).statements, pipeline))); - case SyntaxKind.DefaultClause: - return write(updateDefaultClause(node, - visitNodes((node).statements, pipeline))); - case SyntaxKind.HeritageClause: - return write(updateHeritageClause(node, - visitNodes((node).types, pipeline))); - case SyntaxKind.CatchClause: - return write(updateCatchClause(node, - visitNode((node).variableDeclaration, pipeline), - visitNode((node).block, pipeline))); - case SyntaxKind.PropertyAssignment: - return write(updatePropertyAssignment(node, - visitNode((node).name, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.ShorthandPropertyAssignment: - return write(updateShorthandPropertyAssignment(node, - visitNode((node).name, pipeline))); - case SyntaxKind.EnumMember: - return write(updateEnumMember(node, - visitNode((node).name, pipeline), - visitNode((node).initializer, pipeline))); - case SyntaxKind.JSDocTypeExpression: - return write(updateJSDocTypeExpression(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocArrayType: - return write(updateJSDocArrayType(node, - visitNode((node).elementType, pipeline))); - case SyntaxKind.JSDocUnionType: - return write(updateJSDocUnionType(node, - visitNodes((node).types, pipeline))); - case SyntaxKind.JSDocTupleType: - return write(updateJSDocTupleType(node, - visitNodes((node).types, pipeline))); - case SyntaxKind.JSDocNullableType: - return write(updateJSDocNullableType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocNonNullableType: - return write(updateJSDocNonNullableType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocRecordType: - return write(updateJSDocRecordType(node, - visitNodes((node).members, pipeline))); - case SyntaxKind.JSDocRecordMember: - return write(updateJSDocRecordMember(node, - visitNode((node).name, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocTypeReference: - return write(updateJSDocTypeReference(node, - visitNode((node).name, pipeline), - visitNodes((node).typeArguments, pipeline))); - case SyntaxKind.JSDocOptionalType: - return write(updateJSDocOptionalType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocFunctionType: - return write(updateJSDocFunctionType(node, - visitNodes((node).parameters, pipeline), - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocVariadicType: - return write(updateJSDocVariadicType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocConstructorType: - return write(updateJSDocConstructorType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocThisType: - return write(updateJSDocThisType(node, - visitNode((node).type, pipeline))); - case SyntaxKind.JSDocComment: - return write(updateJSDocComment(node, - visitNodes((node).tags, pipeline))); - case SyntaxKind.JSDocTag: - return write(updateJSDocTag(node, - visitNode((node).tagName, pipeline))); - case SyntaxKind.JSDocParameterTag: - return write(updateJSDocParameterTag(node, - visitNode((node).preParameterName, pipeline), - visitNode((node).typeExpression, pipeline), - visitNode((node).postParameterName, pipeline), - visitNode((node).tagName, pipeline))); - case SyntaxKind.JSDocReturnTag: - return write(updateJSDocReturnTag(node, - visitNode((node).typeExpression, pipeline), - visitNode((node).tagName, pipeline))); - case SyntaxKind.JSDocTypeTag: - return write(updateJSDocTypeTag(node, - visitNode((node).typeExpression, pipeline), - visitNode((node).tagName, pipeline))); - case SyntaxKind.JSDocTemplateTag: - return write(updateJSDocTemplateTag(node, - visitNodes((node).typeParameters, pipeline), - visitNode((node).tagName, pipeline))); - default: - return write(node); - } - } -} diff --git a/src/compiler/transform.ts b/src/compiler/transform.ts index b0ef922fc2f..29a3e5f797f 100644 --- a/src/compiler/transform.ts +++ b/src/compiler/transform.ts @@ -1,405 +1,210 @@ -/// -/// -const FORCE_TRANSFORMS = true; +/// +/// +/// +/// +const FORCE_TRANSFORMS = false; /* @internal */ namespace ts { - export type Visitor = (input: Node, output: (node: Node) => void) => void; - export type LexicalEnvironmentBody = ModuleDeclaration | ModuleBlock | Block | Expression; - export type PipelineOutput = (node: TOut) => void; - export type Pipeline = (input: TIn, output: PipelineOutput, offset?: number) => void; - export type NodeTest = (node: Node) => node is T; - export type TransformationChain = (transformer: Transformer, statements: NodeArray) => NodeArray; - - /** - * Computes the transform flags for a node, given the transform flags of its subtree - * @param node The node to analyze - * @param subtreeFlags Transform flags computed for this node's subtree - */ - export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) { - Debug.assert((subtreeFlags & TransformFlags.NodeExcludes) == 0, "Subtree includes a `ThisNode...` flag."); - let transformFlags: TransformFlags; + export let transformTime = 0; - // Mark transformations needed for each node - let kind = node.kind; - switch (kind) { - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.AbstractKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.ConstKeyword: - return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; - - case SyntaxKind.AwaitExpression: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.ImportEqualsDeclaration: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript; + export type TransformationChain = (node: SourceFile, transformer: Transformer) => SourceFile; - case SyntaxKind.ImportDeclaration: - case SyntaxKind.ExportDeclaration: - case SyntaxKind.ComputedPropertyName: - case SyntaxKind.TemplateExpression: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.ForOfStatement: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6; - - case SyntaxKind.YieldExpression: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6Yield; - - case SyntaxKind.ThisKeyword: - return node.transformFlags = TransformFlags.ThisNodeIsThisKeyword; - - case SyntaxKind.SpreadElementExpression: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6SpreadElement; - - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.ReturnStatement: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsCompletionStatement; - - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6VariableBindingPattern; - - case SyntaxKind.Decorator: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScriptDecorator; - - case SyntaxKind.ModuleDeclaration: - return (node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript) - & ~(node.excludeTransformFlags = TransformFlags.ModuleScopeExcludes); - - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.CallExpression: - return (node.transformFlags = subtreeFlags) - & ~(node.excludeTransformFlags = TransformFlags.CallOrArrayLiteralExcludes); - - case SyntaxKind.PropertyDeclaration: - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; - - case SyntaxKind.BinaryExpression: - if (isDestructuringAssignment(node)) { - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6; - } - break; - - case SyntaxKind.AnyKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.TypeParameter: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.PropertySignature: - return (node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript) - & ~(node.excludeTransformFlags = TransformFlags.TypeExcludes); - - case SyntaxKind.Parameter: - if ((node).questionToken) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - if (subtreeFlags & TransformFlags.ContainsTypeScriptModifier) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; - } - - if ((node).initializer) { - transformFlags |= TransformFlags.ThisNodeIsES6ParameterInitializer; - } - - if ((node).dotDotDotToken) { - transformFlags |= TransformFlags.ThisNodeIsES6RestParameter; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.ParameterScopeExcludes); - - case SyntaxKind.ArrowFunction: - transformFlags = TransformFlags.ThisNodeIsES6; - if (subtreeFlags & TransformFlags.SubtreeContainsLexicalThis) { - transformFlags |= TransformFlags.ThisNodeCapturesLexicalThis; - } - if (node.flags & NodeFlags.Async) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.ArrowFunctionScopeExcludes); - - case SyntaxKind.FunctionExpression: - if ((node).asteriskToken - || transformFlags & TransformFlags.SubtreeContainsES6ParameterOrCapturedThis) { - transformFlags |= TransformFlags.ThisNodeIsES6; - } - - if (node.flags & NodeFlags.Async) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes); - - case SyntaxKind.FunctionDeclaration: - if (!(node).body) { - return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; - } - - transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; - if (node.flags & NodeFlags.Async) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - if ((node).asteriskToken - || node.flags & NodeFlags.Export - || subtreeFlags & TransformFlags.SubtreeContainsES6ParameterOrCapturedThis) { - transformFlags |= TransformFlags.ThisNodeIsES6; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes); - - case SyntaxKind.VariableDeclarationList: - transformFlags = TransformFlags.ThisNodeIsHoistedDeclaration; - if (node.flags & (NodeFlags.Let | NodeFlags.Const)) { - transformFlags |= TransformFlags.ThisNodeIsES6LetOrConst; - } - - return node.transformFlags = subtreeFlags | transformFlags; - - case SyntaxKind.VariableStatement: - if (node.flags & NodeFlags.Export) { - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6; - } - break; - - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - transformFlags = TransformFlags.ThisNodeIsES6; - if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntaxExtension) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.ClassScopeExcludes); - - case SyntaxKind.HeritageClause: - if ((node).token !== SyntaxKind.ExtendsKeyword) { - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; - } - - break; - - case SyntaxKind.ExpressionWithTypeArguments: - if ((node).typeArguments) { - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript; - } - - break; - - case SyntaxKind.Constructor: - if (!(node).body) { - return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes); - - case SyntaxKind.MethodDeclaration: - if (!(node).body) { - return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; - } - - transformFlags = TransformFlags.ThisNodeIsES6; - if (node.flags & NodeFlags.Async) { - transformFlags |= TransformFlags.ThisNodeIsTypeScript; - } - - if (subtreeFlags & TransformFlags.ContainsTypeScriptDecorator - && (node).name.kind === SyntaxKind.ComputedPropertyName) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes); - - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - if (subtreeFlags & TransformFlags.ContainsTypeScriptDecorator - && (node).name.kind === SyntaxKind.ComputedPropertyName) { - transformFlags |= TransformFlags.ThisNodeIsTypeScriptClassSyntaxExtension; - } - - return (node.transformFlags = subtreeFlags | transformFlags) - & ~(node.excludeTransformFlags = TransformFlags.FunctionScopeExcludes); - - case SyntaxKind.ExportAssignment: - if ((node).isExportEquals) { - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript; - } - - return node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsES6; - - default: - if (SyntaxKind.FirstTypeNode <= kind && kind <= SyntaxKind.LastTypeNode) { - return (node.transformFlags = subtreeFlags | TransformFlags.ThisNodeIsTypeScript) - & ~(node.excludeTransformFlags = TransformFlags.TypeExcludes); - } - - break; - } - - return node.transformFlags = subtreeFlags; + interface LexicalEnvironment { + tempFlags: TempFlags; + hoistedVariableDeclarations: VariableDeclaration[]; + hoistedFunctionDeclarations: FunctionDeclaration[]; } - export function runTransformationChain(statements: NodeArray, chain: TransformationChain, - _compilerOptions: CompilerOptions, _currentSourceFile: SourceFile, _resolver: EmitResolver, _generatedNameSet: Map, _nodeToGeneratedName: string[]) { - return transform.runTransformationChain(statements, chain, _compilerOptions, _currentSourceFile, _resolver, _generatedNameSet, _nodeToGeneratedName); + const enum VisitFlags { + StatementBranch = 1 << 1, + ConciseBody = 1 << 2, + LexicalEnvironment = 1 << 3, + LexicalEnvironmentStarted = 1 << 4, + LexicalEnvironmentEnded = 1 << 5, } - - export const enum PipelineFlags { - LexicalEnvironment = 1 << 1, - StatementOrBlock = 1 << 2, - ExpressionOrBlock = 1 << 3, - } - - export interface Transformer { - getEmitResolver(): EmitResolver; - getCompilerOptions(): CompilerOptions; - makeUniqueName(baseName: string): string; - getGeneratedNameForNode(node: Node): Identifier; - nodeHasGeneratedName(node: Node): boolean; - createUniqueIdentifier(baseName: string): Identifier; - createTempVariable(loopVariable: boolean): Identifier; - declareLocal(baseName?: string): Identifier; - hoistVariableDeclaration(name: Identifier): void; - hoistFunctionDeclaration(func: FunctionDeclaration): void; - createParentNavigator(): ParentNavigator; - getRootNode(): SourceFile; - getParentNode(): Node; - getCurrentNode(): Node; - findAncestorNode(match: (node: Node) => node is T): T; - findAncestorNode(match: (node: Node) => boolean): Node; - getDeclarationName(node: DeclarationStatement): Identifier; - getDeclarationName(node: ClassLikeDeclaration): Identifier; - getDeclarationName(node: Declaration): DeclarationName; - getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement): Expression; - pipeNode(input: TIn, pipeline: Pipeline, output: PipelineOutput, flags?: PipelineFlags): void; - pipeNodes(input: TIn[], pipeline: Pipeline, output: PipelineOutput, flags?: PipelineFlags): void; - emitNode(input: TIn, pipeline: Pipeline, output: TOut[], flags?: PipelineFlags, nodeTest?: NodeTest): void; - emitNodes(input: TIn[], pipeline: Pipeline, output: TOut[], flags?: PipelineFlags, nodeTest?: NodeTest): void; - visitNode(input: T, pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): T; - visitNode(input: T, pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): T; - visitNode(input: TIn, pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): TOut; - visitNodes(input: T[], pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): NodeArray; - visitNodes(input: T[], pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): NodeArray; - visitNodes(input: TIn[], pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): NodeArray; - accept(node: T, pipeline: Pipeline, write: PipelineOutput): void; - } - - namespace transform { - // Flags enum to track count of temp variables and a few dedicated names - const enum TempFlags { - Auto = 0x00000000, // No preferred name - CountMask = 0x0FFFFFFF, // Temp variable counter - _i = 0x10000000, // Use/preference flag for '_i' + + export function getTransformationChain(options: CompilerOptions): TransformationChain { + let jsx = options.jsx; + let languageVersion = options.target || ScriptTarget.ES3; + let moduleKind = options.module || ModuleKind.None; + + let transforms: TransformationChain[] = []; + + // Add the TypeScript and Module transforms to the chain. + transforms.push(transformTypeScript); + // transforms.push(transformModule); + + // Add the JSX transform to the chain. + if (jsx === JsxEmit.React) { + transforms.push(transformJsx); } - let transformationRunning: boolean; + // Add the ES6 transform to the chain. + if (languageVersion < ScriptTarget.ES6) { + transforms.push(transformES6); + } + + return chainTransformations(transforms); + } + + export function transformFilesIfNeeded(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain) { + let compilerOptions = host.getCompilerOptions(); + if (compilerOptions.experimentalTransforms) { + return transformFiles(resolver, host, sourceFiles, transformationChain); + } + + return sourceFiles; + } + + export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain) { + // emit output for the __extends helper function + const extendsHelper = ` +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +};`; + + // emit output for the __decorate helper function + const decorateHelper = ` +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); + switch (arguments.length) { + case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); + case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); + case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); + } +};`; + + // emit output for the __metadata helper function + const metadataHelper = ` +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +};`; + + // emit output for the __param helper function + const paramHelper = ` +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +};`; + + const awaiterHelper = ` +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) { + return new Promise(function (resolve, reject) { + 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); } } + function step(verb, value) { + var result = generator[verb](value); + result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject); + } + step("next", void 0); + }); +};`; + + const exportStarHelper = ` +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +}`; + + let compilerOptions = host.getCompilerOptions(); + let languageVersion = compilerOptions.target || ScriptTarget.ES3; let transformFlags: TransformFlags; let generatedNameSet: Map; + let tempVariableNameSet: Map; let nodeToGeneratedName: string[]; let nodeToGeneratedIdentifier: Identifier[]; + let lexicalEnvironmentStackSize: number; + let lexicalEnvironmentStack: LexicalEnvironment[] = []; let tempFlags: TempFlags; let hoistedVariableDeclarations: VariableDeclaration[]; let hoistedFunctionDeclarations: FunctionDeclaration[]; - let compilerOptions: CompilerOptions; - let languageVersion: ScriptTarget; let currentSourceFile: SourceFile; - let resolver: EmitResolver; - - // node stack let nodeStack: NodeStack; - - // single node transform - let nodeTestCallback: (node: Node) => boolean; - let offsetWritten: number; + let currentVisitFlags: VisitFlags; + let requestedVisitFlags: VisitFlags; + let nodeTest: (node: Node) => boolean; + let writeOffset: number; let originalNodes: Node[]; let updatedNode: Node; let updatedNodes: Node[]; - let writeNodeWithOrWithoutNodeTest: (node: Node) => void; - let writeNodeFastOrSlow: (node: Node) => void; + let helpersEmitted: NodeCheckFlags; + let transformer: Transformer = { + getEmitResolver: () => resolver, + getCompilerOptions: () => compilerOptions, + createParentNavigator: () => nodeStack.createParentNavigator(), + getRootNode: () => currentSourceFile, + getParentNode: () => nodeStack.getParent(), + getCurrentNode: () => nodeStack.getNode(), + tryPushNode: node => nodeStack.tryPushNode(node), + pushNode: node => nodeStack.pushNode(node), + popNode: () => nodeStack.popNode(), + findAncestorNode: (match: (node: Node) => boolean) => nodeStack.findAncestorNode(match), + getDeclarationName, + getClassMemberPrefix, + makeUniqueName, + getGeneratedNameForNode, + nodeHasGeneratedName, + createUniqueIdentifier, + createTempVariable, + declareLocal, + hoistVariableDeclaration, + hoistFunctionDeclaration, + emitEmitHelpers, + emitExportStarHelper, + startLexicalEnvironment, + endLexicalEnvironment, + pipeNode, + pipeNodes, + mapNode, + mapNodes, + flattenNode, + visitNode, + visitNodes, + visitStatement, + visitSourceFile, + visitModuleBody, + visitFunctionBody, + visitConciseBody, + accept(node: Node, visitor: (node: Node, write: (node: Node) => void) => void) { + return acceptTransformer(transformer, node, visitor); + } + }; - export function runTransformationChain(statements: NodeArray, chain: TransformationChain, - _compilerOptions: CompilerOptions, _currentSourceFile: SourceFile, _resolver: EmitResolver, _generatedNameSet: Map, _nodeToGeneratedName: string[]) { - Debug.assert(!transformationRunning, "Transformation already running"); - - initializeTransformation(_compilerOptions, _currentSourceFile, _resolver, _generatedNameSet, _nodeToGeneratedName); - - let transformer: Transformer = { - getEmitResolver, - getCompilerOptions, - makeUniqueName, - getGeneratedNameForNode, - nodeHasGeneratedName, - createUniqueIdentifier, - createTempVariable, - declareLocal, - hoistVariableDeclaration, - hoistFunctionDeclaration, - createParentNavigator, - getRootNode, - getParentNode, - getCurrentNode, - findAncestorNode, - getDeclarationName, - getClassMemberPrefix, - pipeNode, - pipeNodes, - emitNode, - emitNodes, - visitNode, - visitNodes, - accept(node: Node, pipeline: Pipeline, write: PipelineOutput) { - ts.accept(transformer, node, pipeline, write); - } - }; + return map(sourceFiles, transformSourceFile); - let result = chain(transformer, statements); - cleanupTransformation(); - return result; - } - - - function initializeTransformation(_compilerOptions: CompilerOptions, _currentSourceFile: SourceFile, _resolver: EmitResolver, _generatedNameSet: Map, - _nodeToGeneratedName: string[]) { - compilerOptions = _compilerOptions; - languageVersion = _compilerOptions.target || ScriptTarget.ES3; - currentSourceFile = _currentSourceFile; - resolver = _resolver; - generatedNameSet = _generatedNameSet; - nodeToGeneratedName = _nodeToGeneratedName; + function transformSourceFile(sourceFile: SourceFile) { + if (isDeclarationFile(sourceFile)) { + return sourceFile; + } + + currentSourceFile = sourceFile; + generatedNameSet = {}; + tempVariableNameSet = {}; + nodeToGeneratedName = []; nodeToGeneratedIdentifier = []; + lexicalEnvironmentStackSize = 0; nodeStack = createNodeStack(); - nodeStack.pushNode(_currentSourceFile); - transformationRunning = true; - } - - function cleanupTransformation() { - compilerOptions = undefined; - languageVersion = undefined; + helpersEmitted = undefined; + + let visited = transformationChain(sourceFile, transformer); + if (visited !== sourceFile) { + visited.identifiers = assign(assign(clone(sourceFile.identifiers), generatedNameSet), tempVariableNameSet); + updateFrom(sourceFile, visited); + } + currentSourceFile = undefined; - resolver = undefined; generatedNameSet = undefined; + tempVariableNameSet = undefined; nodeToGeneratedName = undefined; nodeToGeneratedIdentifier = undefined; + lexicalEnvironmentStackSize = undefined; nodeStack = undefined; - transformationRunning = false; + helpersEmitted = undefined; + + return visited; } // Return the next available name in the pattern _a ... _z, _0, _1, ... @@ -410,7 +215,7 @@ namespace ts { let name = flags === TempFlags._i ? "_i" : "_n"; if (isUniqueName(name)) { tempFlags |= flags; - return name; + return tempVariableNameSet[name] = name; } } while (true) { @@ -422,12 +227,12 @@ namespace ts { ? "_" + String.fromCharCode(CharacterCodes.a + count) : "_" + (count - 26); if (isUniqueName(name)) { - return name; + return tempVariableNameSet[name] = name; } } } } - + // 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 @@ -446,23 +251,23 @@ namespace ts { i++; } } - + function getGeneratedNameForNode(node: Node) { let id = getNodeId(node); return nodeToGeneratedIdentifier[id] || (nodeToGeneratedIdentifier[id] = createIdentifier(getGeneratedNameTextForNode(node, id))); } - + function nodeHasGeneratedName(node: Node) { let id = getNodeId(node); return nodeToGeneratedName[id] !== undefined; } - + function isUniqueName(name: string): boolean { return !resolver.hasGlobalName(name) && !hasProperty(currentSourceFile.identifiers, name) && !hasProperty(generatedNameSet, name); } - + function isUniqueLocalName(name: string, container: Node): boolean { container = getOriginalNode(container); for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) { @@ -475,11 +280,11 @@ namespace ts { } return true; } - + function getGeneratedNameTextForNode(node: Node, id: number) { return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node))); } - + function generateNameForNode(node: Node) { switch (node.kind) { case SyntaxKind.Identifier: @@ -498,61 +303,54 @@ namespace ts { return generateNameForClassExpression(); case SyntaxKind.ComputedPropertyName: case SyntaxKind.Parameter: + case SyntaxKind.TaggedTemplateExpression: return makeTempVariableName(TempFlags.Auto); } } - + function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { let name = node.name.text; // Use module/enum name itself if it is unique, otherwise make a unique variation return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } - + function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { let expr = getExternalModuleName(node); let baseName = expr.kind === SyntaxKind.StringLiteral ? escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; return makeUniqueName(baseName); } - + function generateNameForExportDefault() { return makeUniqueName("default"); } - + function generateNameForClassExpression() { return makeUniqueName("class"); } - - export function getEmitResolver(): EmitResolver { - return resolver; - } - - export function getCompilerOptions(): CompilerOptions { - return compilerOptions; - } - - export function createParentNavigator(): ParentNavigator { + + function createParentNavigator(): ParentNavigator { return nodeStack.createParentNavigator(); } - - export function getRootNode(): SourceFile { + + function getRootNode(): SourceFile { return currentSourceFile; } - - export function getCurrentNode(): Node { + + function getCurrentNode(): Node { return nodeStack.getNode(); } - - export function getParentNode(): Node { + + function getParentNode(): Node { return nodeStack.getParent(); } - + function findAncestorNode(match: (node: Node) => node is T): T; function findAncestorNode(match: (node: Node) => boolean): Node; function findAncestorNode(match: (node: Node) => boolean) { return nodeStack.findAncestorNode(match); } - + function getDeclarationName(node: DeclarationStatement): Identifier; function getDeclarationName(node: ClassLikeDeclaration): Identifier; function getDeclarationName(node: Declaration): DeclarationName; @@ -565,465 +363,583 @@ namespace ts { return getGeneratedNameForNode(node); } } - + function getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement) { - let expression: Expression = getDeclarationName(node); + let expression: LeftHandSideExpression = getDeclarationName(node); if (!(member.flags & NodeFlags.Static)) { expression = createPropertyAccessExpression2( expression, createIdentifier("prototype") ); } - + return expression; } - + function createUniqueIdentifier(baseName: string): Identifier { let name = makeUniqueName(baseName); return createIdentifier(name); } - - function createTempVariable(loopVariable: boolean): Identifier { - let name = makeTempVariableName(loopVariable ? TempFlags._i : TempFlags.Auto); + + function createTempVariable(flags?: TempFlags): Identifier { + let name = makeTempVariableName(flags); return createIdentifier(name); } - + function declareLocal(baseName?: string): Identifier { let local = baseName ? createUniqueIdentifier(baseName) - : createTempVariable(/*loopVariable*/ false); + : createTempVariable(TempFlags.Auto); hoistVariableDeclaration(local); return local; } - + function hoistVariableDeclaration(name: Identifier): void { if (!hoistedVariableDeclarations) { hoistedVariableDeclarations = []; } - + hoistedVariableDeclarations.push(createVariableDeclaration2(name)); } - + function hoistFunctionDeclaration(func: FunctionDeclaration): void { if (!hoistedFunctionDeclarations) { hoistedFunctionDeclarations = []; } - + hoistedFunctionDeclarations.push(func); } - + + function emitEmitHelpers(write: (node: Statement) => void) { + if (compilerOptions.noEmitHelpers) { + return; + } + + if (languageVersion < ScriptTarget.ES6 && shouldEmitHelper(NodeCheckFlags.EmitExtends)) { + write(createRawStatement(extendsHelper)); + helpersEmitted |= NodeCheckFlags.EmitExtends; + } + + if (shouldEmitHelper(NodeCheckFlags.EmitDecorate)) { + write(createRawStatement(decorateHelper)); + helpersEmitted |= NodeCheckFlags.EmitDecorate; + } + + if (shouldEmitHelper(NodeCheckFlags.EmitParam)) { + write(createRawStatement(paramHelper)); + helpersEmitted |= NodeCheckFlags.EmitParam; + } + + if (shouldEmitHelper(NodeCheckFlags.EmitAwaiter)) { + write(createRawStatement(awaiterHelper)); + helpersEmitted |= NodeCheckFlags.EmitAwaiter; + } + } + + function emitExportStarHelper(write: (node: Statement) => void) { + if (shouldEmitHelper(NodeCheckFlags.EmitExportStar)) { + write(createRawStatement(exportStarHelper)); + } + } + + function shouldEmitHelper(flags: NodeCheckFlags) { + return !(helpersEmitted & flags) + && !!(resolver.getNodeCheckFlags(currentSourceFile) & flags); + } + function aggregateTransformFlags(node: Node) { if (!node) { return; } - + aggregateTransformFlagsForThisNodeAndSubtree(node); } - + function aggregateTransformFlagsForThisNodeAndSubtree(node: Node) { if (node.transformFlags === undefined) { if (node.flags & NodeFlags.Ambient) { - // Ambient nodes are marked as TypeScript early to prevent an unnecessary walk of the tree + // Ambient nodes are marked as TypeScript early to prevent an unnecessary walk of the tree return node.transformFlags = TransformFlags.ThisNodeIsTypeScript; } - + let transformFlagsOfChildren = aggregateTransformFlagsOfChildren(node); return computeTransformFlagsForNode(node, transformFlagsOfChildren); } - + return node.transformFlags & ~node.excludeTransformFlags; } - + function aggregateTransformFlagsOfChildren(node: Node) { let saveTransformFlags = transformFlags; transformFlags = 0; - + forEachChild(node, aggregateTransformFlagsForChildNode); - + let transformFlagsOfChildren = transformFlags; transformFlags = saveTransformFlags; - + return transformFlagsOfChildren & ~TransformFlags.NodeExcludes; } - + function aggregateTransformFlagsForChildNode(child: Node) { transformFlags |= aggregateTransformFlagsForThisNodeAndSubtree(child); } - - function verifyNode(node: Node): node is TOut { - if (!nodeTestCallback(node)) { - Debug.fail("Incorrect node kind after visit"); - return false; - } - return true; + + function nextNodeIsLexicalEnvironment() { + requestedVisitFlags |= VisitFlags.LexicalEnvironment; } - - /** - * A function passed to a visitor callback that can be used to write a single node. - * @param node The node to write - */ + + function nextNodeIsStatementBranch() { + requestedVisitFlags |= VisitFlags.StatementBranch; + } + + function nextNodeIsConciseBody() { + requestedVisitFlags |= VisitFlags.ConciseBody; + } + + function markLexicalEnvironmentStart() { + currentVisitFlags |= VisitFlags.LexicalEnvironmentStarted; + } + + function resetLexicalEnvironmentStart() { + currentVisitFlags &= ~VisitFlags.LexicalEnvironmentStarted; + } + + function markLexicalEnvironmentEnd() { + currentVisitFlags |= VisitFlags.LexicalEnvironmentEnded; + } + + function resetLexicalEnvironmentEnd() { + currentVisitFlags &= ~VisitFlags.LexicalEnvironmentEnded; + } + + function thisNodeIsLexicalEnvironment() { + return !!(currentVisitFlags & VisitFlags.LexicalEnvironment); + } + + function lexicalEnvironmentStartWasMarked() { + return !!(currentVisitFlags & VisitFlags.LexicalEnvironmentStarted); + } + + function lexicalEnvironmentEndWasMarked() { + return !!(currentVisitFlags & VisitFlags.LexicalEnvironmentEnded); + } + + function thisNodeIsStatementBranch() { + return !!(currentVisitFlags & VisitFlags.StatementBranch); + } + + function thisNodeIsConciseBody() { + return !!(currentVisitFlags & VisitFlags.ConciseBody); + } + function writeNode(node: Node) { if (!node) { return; } - - writeNodeWithOrWithoutNodeTest(node); - } - - function writeNodeWithNodeTest(node: Node) { - if (verifyNode(node)) { - writeNodeWithoutNodeTest(node); - } - } - - function writeNodeWithoutNodeTest(node: Node) { + + Debug.assert(!nodeTest || nodeTest(node), "Wrong node type after visit."); aggregateTransformFlags(node); - writeNodeFastOrSlow(node); - } - - function writeNodeSlow(node: Node) { - updatedNode = node; - writeNodeFastOrSlow = writeNodeFast; - } - - function writeNodeFast(node: Node) { - Debug.fail("Node already written"); - } - - function writeExpressionOrBlockSlow(node: Node) { - if (!updatedNode) { - if (isExpressionNode(node)) { - updatedNode = node; - } - else { - updatedNode = createBlock([]); - writeNodeFastOrSlow = writeExpressionOrBlockFast; - writeNodeFastOrSlow(node); - } - } - else { - let previousNode = updatedNode; - updatedNode = createBlock([]); - writeNodeFastOrSlow = writeExpressionOrBlockFast; - writeNodeFastOrSlow(previousNode); - writeNodeFastOrSlow(node); - } - } - - function writeExpressionOrBlockFast(node: Node) { - if (isExpressionNode(node)) { - (updatedNode).statements.push(createReturnStatement(node)); - } - else { - Debug.assert(isStatementNode(node)); - (updatedNode).statements.push(node); - } - } - - function writeStatementOrBlockSlow(node: Node) { - Debug.assert(isStatementNode(node)); if (!updatedNode) { updatedNode = node; } - else { - let previousNode = updatedNode; - updatedNode = createBlock([]); - writeNodeFastOrSlow = writeStatementOrBlockFast; - writeNodeFastOrSlow(previousNode); - writeNodeFastOrSlow(node); + else if (thisNodeIsStatementBranch()) { + if (!updatedNodes) { + updatedNodes = []; + writeStatementNode(updatedNode); + updatedNode = createBlock(updatedNodes); + } + writeStatementNode(node); } - } - - function writeStatementOrBlockFast(node: Node) { - Debug.assert(isStatementNode(node)); - (updatedNode).statements.push(node); - } - - function writeNodeToNodeArraySlow(node: Node) { - if (offsetWritten === originalNodes.length || originalNodes[offsetWritten] !== node) { - updatedNodes = originalNodes.slice(0, offsetWritten); - updatedNodes.push(node); - writeNodeFastOrSlow = writeNodeToNodeArrayFast; + else if (thisNodeIsConciseBody()) { + if (!updatedNodes) { + updatedNodes = []; + writeFunctionBodyNode(updatedNode); + updatedNode = createBlock(updatedNodes); + } + writeFunctionBodyNode(node); } else { - offsetWritten++; + Debug.fail("Too many nodes written to output."); } } - - function writeNodeToNodeArrayFast(node: Node) { + + function writeStatementNode(node: Node) { + Debug.assert(isStatementNode(updatedNode), "Statement expected."); updatedNodes.push(node); } - + + function writeFunctionBodyNode(node: Node) { + if (isExpressionNode(node)) { + updatedNodes.push(createReturnStatement(node)); + } + else { + Debug.assert(isStatementNode(node), "Statement or expression expected."); + updatedNodes.push(node); + } + } + + function writeNodeToNodeArray(node: Node) { + if (!node) { + return; + } + + Debug.assert(!nodeTest || nodeTest(node), "Wrong node type after visit."); + aggregateTransformFlags(node); + if (updatedNodes) { + updatedNodes.push(node); + } + else if (writeOffset < originalNodes.length && originalNodes[writeOffset] === node) { + writeOffset++; + } + else { + updatedNodes = originalNodes.slice(0, writeOffset); + updatedNodes.push(node); + } + } + function readNode(): Node { + Debug.assert(!!updatedNode, "Not enough nodes written to output."); return updatedNode; } - + function readNodeArray(): NodeArray { if (updatedNodes) { return createNodeArray(updatedNodes, /*location*/ >originalNodes); } - else if (offsetWritten !== originalNodes.length) { - return createNodeArray(originalNodes.slice(0, offsetWritten), /*location*/ >originalNodes); + else if (writeOffset !== originalNodes.length) { + return createNodeArray(originalNodes.slice(0, writeOffset), /*location*/ >originalNodes); } else { return createNodeArray(originalNodes); } } - - /** - * Pipes an input node (or nodes) into an output callback by passing it through a visitor callback. - * @remarks - * The primary responsibility of `pipeOneOrMany` is to execute the `visitor` callback for each - * input node, passing the input node and the output callback. - * This function also manages when new lexical environments are introduced, and tracks temporary - * variables and hoisted variable and function declarations. - */ - function pipeOneOrMany(inputNode: TIn, inputNodes: TIn[], pipeline: Pipeline, output: (node: TOut) => void, flags: PipelineFlags): void { - if (!inputNode && !inputNodes) { - return; + + function visitNodeOrNodes(node: Node, nodes: Node[], start: number, count: number, visitor: (node: Node, write: (node: Node) => void) => void, + write: (node: Node) => void, readNode?: () => Node, readNodes?: () => NodeArray, out?: Node[], test?: (node: Node) => boolean): Node | NodeArray { + let resultNode: Node; + let resultNodes: NodeArray; + let savedOriginalNodes: typeof originalNodes; + let savedWriteOffset: typeof writeOffset; + let savedUpdatedNode: typeof updatedNode; + let savedUpdatedNodes: typeof updatedNodes; + let savedNodeTest: typeof nodeTest; + let savedCurrentVisitFlags: typeof currentVisitFlags; + + // If we have no work to do, clear the requested visit flags and exit + if (!node && !nodes) { + // If we don't have a `read` argument, then we should not affect + // requested flags as we are not directly manipulating nodes. + if (readNode || readNodes) { + requestedVisitFlags = undefined; + } + + return undefined; } - - // Preserve the current environment on the call stack as we descend into the tree - let savedTempFlags: number; - let savedHoistedVariableDeclarations: VariableDeclaration[]; - let savedHoistedFunctionDeclarations: FunctionDeclaration[]; - - // If we are starting a new lexical environment, we need to reinitialize the lexical - // environment state as well - if (flags & PipelineFlags.LexicalEnvironment) { - savedTempFlags = tempFlags; - savedHoistedVariableDeclarations = hoistedVariableDeclarations; - savedHoistedFunctionDeclarations = hoistedFunctionDeclarations; - - tempFlags = 0; - hoistedVariableDeclarations = undefined; - hoistedFunctionDeclarations = undefined; + + if (!visitor) { + visitor = identityVisitor; } - - if (inputNode) { - let nodeWasPushed = nodeStack.tryPushNode(inputNode); - pipeline(inputNode, output); - if (nodeWasPushed) { - nodeStack.popNode(); + + // Establish the new environment, but only if we are going to read a result. + // If we don't have a `read` argument, then we are piping values to a callback. + if (readNode || readNodes) { + // Preserve the previous environment on the call stack as we descend into the tree + savedOriginalNodes = originalNodes; + savedWriteOffset = writeOffset; + savedUpdatedNode = updatedNode; + savedUpdatedNodes = updatedNodes; + savedNodeTest = nodeTest; + savedCurrentVisitFlags = currentVisitFlags; + + originalNodes = nodes; // This will be `undefined` if visiting a single node + writeOffset = 0; + updatedNode = undefined; + updatedNodes = out; // This will be `undefined` unless we are emitting nodes to an existing array. + nodeTest = test; + currentVisitFlags = requestedVisitFlags; // Here we copy any requested flags and reset the request. + requestedVisitFlags = undefined; + + // These flags indicate a new lexical environment should be introduced when/if we visit the children of this node. + if (thisNodeIsLexicalEnvironment()) { + pushLexicalEnvironment(); } } - else { - // For perf reasons, we push `undefined` as the current node and set it to the correct - // value for each iteration of the loop below. This avoids excessive push and pop - // operations on `nodeStack`. - nodeStack.pushNode(/*node*/ undefined); - + + // Try to push the node (or `undefined` if we are visiting an array) to the top + // of the stack. + // For perf reasons, we push `undefined` as the current node for an array and + // later set it to the correctvalue for each iteration of the loop below. This + // avoids excessive push and pop operations on `nodeStack`. + let wasPushed = nodeStack.tryPushNode(node); + + if (node) { + // visit the input node + visitor(node, write); + } + else if (nodes) { + // Fix start and count + let len = nodes.length; + start = start < 0 ? 0 : start || 0; + count = count > len - start ? len - start : count || len - start; + // Visit each input node - let offset = 0; - for (let node of inputNodes) { + for (let i = 0; i < count; ++i) { + let node = nodes[i + start]; nodeStack.setNode(node); - pipeline(node, output, offset++); + visitor(node, write); } - - // For the perf reasons mentioned above, we pop the current node at the end of the loop. + } + + // If we pushed a node (or `undefined`) onto the stack, we need to + // pop the node from the stack here. + if (wasPushed) { nodeStack.popNode(); } - - // If we established a new lexical environment, we need to write any hoisted variables or - // function declarations to the end of the output. - if (flags & PipelineFlags.LexicalEnvironment) { - if (hoistedVariableDeclarations) { - var stmt = createVariableStatement2(createVariableDeclarationList(hoistedVariableDeclarations)); - output(stmt); + + // If we don't have a `read` argument, we don't need to restore state + if (readNode || readNodes) { + // Read the result if the `read` callback was supplied + if (readNode) { + resultNode = readNode(); } - else if (hoistedFunctionDeclarations) { - for (let decl of hoistedFunctionDeclarations) { - output(decl); + else if (readNodes) { + resultNodes = readNodes(); + } + + // If a new lexical environment had been requested, we need to include it here + if (thisNodeIsLexicalEnvironment()) { + if (hoistedVariableDeclarations || hoistedFunctionDeclarations) { + let statements: Statement[]; + if (isSourceFile(resultNode) || isModuleBody(resultNode) || isFunctionBody(resultNode)) { + // ensure we have a fresh node + if (resultNode === node) { + resultNode = cloneNode(resultNode, /*location*/ resultNode, resultNode.flags); + } + + statements = (resultNode).statements; + } + else { + Debug.assert(isExpression(resultNode), "Expected the result of a lexical enviornment to be a SourceFile, ModuleBlock, Block, or Expression"); + statements = [createReturnStatement(resultNode)]; + resultNode = createBlock(statements); + } + + if (hoistedVariableDeclarations) { + statements.push(createVariableStatement2(createVariableDeclarationList(hoistedVariableDeclarations))); + } + + if (hoistedFunctionDeclarations) { + statements.push(...hoistedFunctionDeclarations); + } } + + popLexicalEnvironment(); } - - // Restore the previous lexical environment - tempFlags = savedTempFlags; - hoistedVariableDeclarations = savedHoistedVariableDeclarations; - hoistedFunctionDeclarations = savedHoistedFunctionDeclarations; + + // Restore the previous environment + originalNodes = savedOriginalNodes; + writeOffset = savedWriteOffset; + updatedNode = savedUpdatedNode; + updatedNodes = savedUpdatedNodes; + nodeTest = savedNodeTest; + currentVisitFlags = savedCurrentVisitFlags; } + + return resultNode || resultNodes; } - - function emitOneWithLexicalEnvironment(input: Node, pipeline: Pipeline, flags: PipelineFlags, nodeTest: NodeTest): Node { - if (isBlock(input)) { - return updateBlock(input, visitNodes(input.statements, pipeline, flags)); - } - else if (isModuleBlock(input)) { - return updateModuleBlock(input, visitNodes(input.statements, pipeline, flags)); - } - else if (isExpression(input)) { - return emitOne(input, pipeline, flags | PipelineFlags.ExpressionOrBlock, nodeTest); + + function pipeNodeOrNodes(node: TIn, nodes: TIn[], start: number, count: number, through: Through, out: ((node: TOut) => void) | TOut[]): NodeArray { + let write: (node: Node) => void; + let readNodes: () => NodeArray; + let outputArray: TOut[]; + if (typeof out === "function") { + write = out as (node: Node) => void; } else { - return emitOne(input, pipeline, flags, nodeTest); + write = writeNodeToNodeArray; + readNodes = readNodeArray; + outputArray = out as TOut[]; + } + + return >visitNodeOrNodes(node, nodes, start, count, through, write, /*readNode*/ undefined, readNodes, outputArray, /*test*/ undefined); + } + + + function identityVisitor(node: Node, write: (node: Node) => void): void { + write(node); + } + + function pushLexicalEnvironment(): void { + // Save the current lexical environment. Rather than resizing the array + // we adjust the stack size variable. This allows us to reuse existing object's we've + // already allocated between transformations to avoid allocation and GC overhead during + // transformation. + let savedLexicalEnvironment: LexicalEnvironment; + if (lexicalEnvironmentStackSize < lexicalEnvironmentStack.length) { + savedLexicalEnvironment = lexicalEnvironmentStack[lexicalEnvironmentStackSize]; + } + else { + savedLexicalEnvironment = lexicalEnvironmentStack[lexicalEnvironmentStackSize] = {}; + } + + savedLexicalEnvironment.tempFlags = tempFlags; + savedLexicalEnvironment.hoistedVariableDeclarations = hoistedVariableDeclarations; + savedLexicalEnvironment.hoistedFunctionDeclarations = hoistedFunctionDeclarations; + lexicalEnvironmentStackSize++; + + tempFlags = 0; + hoistedVariableDeclarations = undefined; + hoistedFunctionDeclarations = undefined; + } + + function popLexicalEnvironment(): void { + // Restore the previous lexical environment. + let savedLexicalEnvironment = lexicalEnvironmentStack[--lexicalEnvironmentStackSize]; + tempFlags = savedLexicalEnvironment.tempFlags; + hoistedVariableDeclarations = savedLexicalEnvironment.hoistedVariableDeclarations; + hoistedFunctionDeclarations = savedLexicalEnvironment.hoistedFunctionDeclarations; + } + + function writeLexicalEnvironment(write: (node: Statement) => void): void { + if (hoistedVariableDeclarations) { + write(createVariableStatement2(createVariableDeclarationList(hoistedVariableDeclarations))); + } + + if (hoistedFunctionDeclarations) { + forEach(hoistedFunctionDeclarations, write); } } - - function emitOne(input: TIn, pipeline: Pipeline, flags: PipelineFlags, nodeTest: NodeTest): TOut { - // Preserve the current environment on the call stack as we descend into the tree - let savedUpdatedNode = updatedNode; - let savedNodeTestCallback = nodeTestCallback; - let savedWriteNodeWithOrWithoutNodeTest = writeNodeWithOrWithoutNodeTest; - let savedWriteNodeFastOrSlow = writeNodeFastOrSlow; - - // Establish the new environment - updatedNode = undefined; - nodeTestCallback = nodeTest; - writeNodeWithOrWithoutNodeTest = nodeTest ? writeNodeWithNodeTest : writeNodeWithoutNodeTest; - writeNodeFastOrSlow = flags & PipelineFlags.StatementOrBlock - ? writeStatementOrBlockSlow - : flags & PipelineFlags.ExpressionOrBlock - ? writeExpressionOrBlockSlow - : writeNodeSlow; - // Pipe the input node into the output - pipeOneOrMany(input, undefined, pipeline, writeNode, flags); - - // Read the result node - let result = readNode(); - - // Restore the previous environment - updatedNode = savedUpdatedNode; - nodeTestCallback = savedNodeTestCallback; - writeNodeWithOrWithoutNodeTest = savedWriteNodeWithOrWithoutNodeTest; - writeNodeFastOrSlow = savedWriteNodeFastOrSlow; - - return result; + function startLexicalEnvironment(): void { + pushLexicalEnvironment(); } - - function emitOneOrMany(inputNode: TIn, inputNodes: TIn[], pipeline: Pipeline, output: TOut[], flags: PipelineFlags, nodeTest: (node: Node) => node is TOut): NodeArray { - // Exit early if we have nothing to do - if (!inputNode && !inputNodes) { - return undefined; - } - - // Preserve the current environment on the call stack as we descend into the tree - let savedOffsetWritten = offsetWritten; - let savedOriginalNodes = originalNodes; + + function endLexicalEnvironment(out: ((node: Statement) => void) | Statement[]): void { + let write: (node: Node) => void; let savedUpdatedNodes = updatedNodes; - let savedNodeTestCallback = nodeTestCallback; - let savedWriteNodeWithOrWithoutNodeTest = writeNodeWithOrWithoutNodeTest; - let savedWriteNodeFastOrSlow = writeNodeFastOrSlow; - - // Establish the new environment - offsetWritten = 0; - originalNodes = inputNodes; - updatedNodes = output; - nodeTestCallback = nodeTest; - writeNodeWithOrWithoutNodeTest = nodeTest ? writeNodeWithNodeTest : writeNodeWithoutNodeTest; - writeNodeFastOrSlow = output ? writeNodeToNodeArrayFast : writeNodeToNodeArraySlow; - - // Pipe the input nodes to the output array through a pipeline - pipeOneOrMany(inputNode, inputNodes, pipeline, writeNode, flags); - - // Read the output array - output = >readNodeArray(); - - // Restore previous environment - offsetWritten = savedOffsetWritten; - originalNodes = savedOriginalNodes; - updatedNodes = savedUpdatedNodes; - nodeTestCallback = savedNodeTestCallback; - writeNodeFastOrSlow = savedWriteNodeFastOrSlow; - writeNodeWithOrWithoutNodeTest = savedWriteNodeWithOrWithoutNodeTest; - - return createNodeArray(output); - - // 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); - // } - // } - // } - // } - } - - /** - * Pipelines the results of visiting a single input node to an output callback function. - * @param input The source node to visit. - * @param pipeline The callback to execute as we visit each node in the source. - * @param output The callback passed to `visitor` to write each visited node. - * @param flags Flags that affect the pipeline. - */ - function pipeNode(input: TIn, pipeline: Pipeline, output: PipelineOutput, flags?: PipelineFlags): void { - pipeOneOrMany(input, undefined, pipeline, output, flags); - } - - /** - * Pipelines the results of visiting each node from an input source to an output callback function. - * @param input The source nodes to visit. - * @param pipeline The callback to execute as we visit each node in the source. - * @param output The callback passed to `visitor` to write each visited node. - * @param flags Flags that affect the pipeline. - */ - function pipeNodes(input: TIn[], pipeline: Pipeline, output: PipelineOutput, flags?: PipelineFlags): void { - pipeOneOrMany(undefined, input, pipeline, output, flags); - } - - /** - * Writes the result from visiting a single input node to an output node array. - * @param input The source node to visit. - * @param pipeline The callback to execute as we visit each node in the source. - * @param output The destination node array to which to write the results from visiting each node. - * @param flags Flags that affect the pipeline. - */ - function emitNode(input: TIn, pipeline: Pipeline, output: TOut[], flags?: PipelineFlags, nodeTest?: NodeTest): void { - emitOneOrMany(input, undefined, pipeline, output, flags, nodeTest); - } - - /** - * Writes the result from visiting each node from an input source to an output node array. - * @param input The source nodes to visit. - * @param pipeline The callback to execute as we visit each node in the source. - * @param output The destination node array to which to write the results from visiting each node. - * @param flags Flags that affect the pipeline. - */ - function emitNodes(input: TIn[], pipeline: Pipeline, output: TOut[], flags?: PipelineFlags, nodeTest?: NodeTest): void { - emitOneOrMany(undefined, input, pipeline, output, flags, nodeTest); - } - - function visitNode(node: T, visitor: Visitor, flags?: PipelineFlags): T; - function visitNode(node: TIn, visitor: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): TOut; - function visitNode(node: TIn, visitor: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): TOut { - if (!node) { - return undefined; + if (typeof out === "function") { + write = out as (node: Statement) => void; } - - return flags & PipelineFlags.LexicalEnvironment - ? emitOneWithLexicalEnvironment(node, visitor, flags, nodeTest) - : emitOne(node, visitor, flags, nodeTest); + else { + updatedNodes = out as Statement[]; + write = writeNodeToNodeArray; + } + + writeLexicalEnvironment(write); + popLexicalEnvironment(); + + updatedNodes = savedUpdatedNodes; } - - function visitNodes(nodes: T[], pipeline: Visitor, flags?: PipelineFlags): NodeArray; - function visitNodes(nodes: TIn[], pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): NodeArray; - function visitNodes(nodes: TIn[], pipeline: Pipeline, flags?: PipelineFlags, nodeTest?: NodeTest): NodeArray { - return emitOneOrMany(undefined, nodes, pipeline, undefined, flags, nodeTest); + + function pipeNode(node: TIn, through: Through, out: ((node: TOut) => void) | TOut[]): void { + pipeNodeOrNodes(node, /*nodes*/ undefined, /*start*/ undefined, /*end*/ undefined, through, out); + } + + function pipeNodes(nodes: TIn[], through: Through, out: ((node: TOut) => void) | TOut[], start?: number, count?: number): void { + pipeNodeOrNodes(/*node*/ undefined, nodes, start, count, through, out); + } + + function mapNode(node: TIn, through: Through): TOut { + return visitNodeOrNodes(node, /*nodes*/ undefined, /*start*/ undefined, /*end*/ undefined, through, writeNode, readNode, /*readNodes*/ undefined, /*out*/ undefined); + } + + function mapNodes(nodes: TIn[], through: (node: TIn, write: (node: TOut) => void) => void, start?: number, count?: number): TOut[] { + return >visitNodeOrNodes(/*node*/ undefined, nodes, start, count, through, writeNodeToNodeArray, /*readNode*/ undefined, readNodeArray, /*out*/ []); + } + + function flattenNode(node: TIn, through: Through): TOut[] { + return >visitNodeOrNodes(node, /*nodes*/ undefined, /*start*/ undefined, /*end*/ undefined, through, writeNodeToNodeArray, /*readNode*/ undefined, readNodeArray, /*out*/ []); + } + + function visitNode(node: T, visitor: (node: Node, write: (node: Node) => void) => void, test: (node: Node) => node is T): T { + return visitNodeOrNodes(node, /*nodes*/ undefined, /*start*/ undefined, /*end*/ undefined, visitor, writeNode, readNode, /*readNodes*/ undefined, /*out*/ undefined, test); + } + + function visitNodes(nodes: T[], visitor: (node: Node, write: (node: Node) => void) => void, test: (node: Node) => node is T, start?: number, count?: number): NodeArray { + return >visitNodeOrNodes(/*node*/ undefined, nodes, start, count, visitor, writeNodeToNodeArray, /*readNode*/ undefined, readNodeArray, /*out*/ undefined, test); + } + + function visitSourceFile(node: SourceFile, visitor: (node: Node, write: (node: Node) => void) => void): SourceFile { + requestedVisitFlags |= VisitFlags.LexicalEnvironment; + return visitNode(node, visitor, isSourceFile); + } + + function visitModuleBody(node: ModuleBody, visitor: (node: Node, write: (node: Node) => void) => void): ModuleBody { + if (isModuleBlock(node)) { + requestedVisitFlags |= VisitFlags.LexicalEnvironment; + } + + return visitNode(node, visitor, isModuleBody); + } + + function visitFunctionBody(node: FunctionBody, visitor: (node: Node, write: (node: Node) => void) => void): FunctionBody { + requestedVisitFlags |= VisitFlags.LexicalEnvironment; + return visitNode(node, visitor, isBlock); + } + + function visitConciseBody(node: ConciseBody, visitor: (node: Node, write: (node: Node) => void) => void): ConciseBody { + requestedVisitFlags |= VisitFlags.ConciseBody | VisitFlags.LexicalEnvironment; + return visitNode(node, visitor, isConciseBody); + } + + function visitStatement(node: Statement, visitor: (node: Node, write: (node: Node) => void) => void): Statement { + requestedVisitFlags |= VisitFlags.StatementBranch; + return visitNode(node, visitor, isStatementNode); } } + + export function chainTransformations(transformations: TransformationChain[]): TransformationChain { + switch (transformations.length) { + case 0: return identityTransformation; + case 1: return createUnaryTransformationChain(transformations[0]); + case 2: return createBinaryTransformationChain(transformations[0], transformations[1]); + case 3: return createTrinaryTransformationChain(transformations[0], transformations[1], transformations[2]); + default: return createNaryTransformationChain(transformations); + } + } + + function runTransformation(chain: TransformationChain, node: SourceFile, transformer: Transformer) { + let start = new Date().getTime(); + let transformed = chain(node, transformer); + transformTime += new Date().getTime() - start; + return transformed; + } + + function createUnaryTransformationChain(only: TransformationChain): TransformationChain { + return (node, transformer) => { + if (only) node = runTransformation(only, node, transformer); + return node; + }; + } + + function createBinaryTransformationChain(first: TransformationChain, second: TransformationChain): TransformationChain { + return (node, transformer) => { + if (first) node = runTransformation(first, node, transformer); + if (second) node = runTransformation(second, node, transformer); + return node; + }; + } + + function createTrinaryTransformationChain(first: TransformationChain, second: TransformationChain, third: TransformationChain): TransformationChain { + return (node, transformer) => { + if (first) node = runTransformation(first, node, transformer); + if (second) node = runTransformation(second, node, transformer); + if (third) node = runTransformation(third, node, transformer); + return node; + }; + } + + function createNaryTransformationChain(transformations: TransformationChain[]): TransformationChain { + return (node, transformer) => { + for (let transformation of transformations) { + if (transformation) node = runTransformation(transformation, node, transformer); + } + return node; + }; + } + + function identityTransformation(node: SourceFile, transformer: Transformer) { + return node; + } } \ No newline at end of file diff --git a/src/compiler/transforms/chain.ts b/src/compiler/transforms/chain.ts deleted file mode 100644 index 08deafe9189..00000000000 --- a/src/compiler/transforms/chain.ts +++ /dev/null @@ -1,71 +0,0 @@ -/// -/// -/// -/// -/*@internal*/ -namespace ts.transform { - - export let transformTime = 0; - - export function getTransformationChain(options: CompilerOptions): TransformationChain { - if ((options.target || ScriptTarget.ES3) < ScriptTarget.ES6) { - return chainTransformations([toES6, toES5]); - } - - return chainTransformations([toES6]); - } - - export function chainTransformations(transformations: TransformationChain[]): TransformationChain { - switch (transformations.length) { - case 0: return identityTransformation; - case 1: return createUnaryTransformationChain(transformations[0]); - case 2: return createBinaryTransformationChain(transformations[0], transformations[1]); - case 3: return createTrinaryTransformationChain(transformations[0], transformations[1], transformations[2]); - default: return createNaryTransformationChain(transformations); - } - } - - function runTransformation(chain: TransformationChain, transformer: Transformer, statements: NodeArray) { - let start = new Date().getTime(); - let transformed = chain(transformer, statements); - transformTime += new Date().getTime() - start; - return transformed; - } - - function createUnaryTransformationChain(only: TransformationChain) { - return function (transformer: Transformer, statements: NodeArray) { - if (only) statements = runTransformation(only, transformer, statements); - return statements; - }; - } - - function createBinaryTransformationChain(first: TransformationChain, second: TransformationChain) { - return function (transformer: Transformer, statements: NodeArray) { - if (first) statements = runTransformation(first, transformer, statements); - if (second) statements = runTransformation(second, transformer, statements); - return statements; - }; - } - - function createTrinaryTransformationChain(first: TransformationChain, second: TransformationChain, third: TransformationChain) { - return function (transformer: Transformer, statements: NodeArray) { - if (first) statements = runTransformation(first, transformer, statements); - if (second) statements = runTransformation(second, transformer, statements); - if (third) statements = runTransformation(third, transformer, statements); - return statements; - }; - } - - function createNaryTransformationChain(transformations: TransformationChain[]) { - return function (transformer: Transformer, statements: NodeArray) { - for (let transformation of transformations) { - if (transformation) statements = runTransformation(transformation, transformer, statements); - } - return statements; - }; - } - - function identityTransformation(transformer: Transformer, statements: NodeArray): NodeArray { - return statements; - } -} \ No newline at end of file diff --git a/src/compiler/transforms/es5.ts b/src/compiler/transforms/es5.ts deleted file mode 100644 index d880c6427a4..00000000000 --- a/src/compiler/transforms/es5.ts +++ /dev/null @@ -1,560 +0,0 @@ -/// -/*@internal*/ -namespace ts { - export function toES5(transformer: Transformer, statements: NodeArray) { - let { - accept, - visitNode, - visitNodes, - emitNode, - emitNodes, - pipeNode, - pipeNodes, - getParentNode, - findAncestorNode, - declareLocal, - getGeneratedNameForNode, - createTempVariable, - hoistVariableDeclaration, - getDeclarationName, - getClassMemberPrefix, - } = transformer; - let currentSourceFile = transformer.getRootNode(); - - return visitNodes(statements, transformNode, PipelineFlags.LexicalEnvironment); - - /** - * 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(node: Node, write: (node: Node) => void): void { - if (!node) { - return; - } - - // Debug.assert( - // !needsTransform(node, TransformFlags.ThisNodeNeedsTransformToES6), - // "Cannot transform node with post-ES6 syntax."); - - if (node.transformFlags & TransformFlags.ThisNodeNeedsTransformToES5) { - transformNodeWorker(node, write); - } - else if (node.flags & NodeFlags.GeneratedSuper && isExpressionStatement(node)) { - transformInitialSuperCall(node, write); - } - else if (node.transformFlags & TransformFlags.SubtreeNeedsTransformToES5) { - accept(node, transformNode, write); - } - else { - write(node); - } - } - - /** - * Transforms a node from ES6 to ES5. - * @param context Context information for the transform. - * @param node The node to transform. - */ - function transformNodeWorker(node: Node, write: (node: Node) => void): void { - switch (node.kind) { - case SyntaxKind.ClassDeclaration: - return transformClassDeclaration(node, write); - - case SyntaxKind.ClassExpression: - return transformClassExpression(node, write); - - case SyntaxKind.Parameter: - return transformParameter(node, write); - - case SyntaxKind.FunctionDeclaration: - return transformFunctionDeclaration(node, write); - - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionExpression: - return transformFunctionExpression(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(node, transformNode, write); - } - } - - function transformClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void) { - let name = getDeclarationName(node); - let classInitExpr = transformClassLikeDeclaration(node, name); - let baseTypeNode = getClassExtendsHeritageClauseElement(node); - let varDecl = createVariableDeclaration2(name, classInitExpr); - let varDecls = createVariableDeclarationList([varDecl]); - let varStmt = createVariableStatement2(varDecls, /*location*/ node); - return write(varStmt); - } - - function transformClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void) { - let name = getDeclarationName(node); - return write(transformClassLikeDeclaration(node, name)); - } - - function transformClassLikeDeclaration(node: ClassLikeDeclaration, name: Identifier): LeftHandSideExpression { - let baseTypeNode = getClassExtendsHeritageClauseElement(node); - let classBody = createBlock([]); - emitNode(node, transformClassBody, classBody.statements); - - let superExpr = baseTypeNode ? visitNode(baseTypeNode.expression, transformNode) : undefined; - let superName = baseTypeNode ? createIdentifier("_super") : undefined; - let superParam = baseTypeNode ? createParameter2(superName) : undefined; - let classDecl = createFunctionExpression2(/*name*/ undefined, baseTypeNode ? [superParam] : [], classBody); - let parenExpr = createParenthesizedExpression(classDecl); - let callExpr = createCallExpression2(parenExpr, baseTypeNode ? [superExpr] : undefined); - return callExpr; - } - - function transformClassBody(node: ClassLikeDeclaration, write: (node: Statement) => void): void { - let name = getDeclarationName(node); - let baseTypeNode = getClassExtendsHeritageClauseElement(node); - emitExtendsCall(node, name, baseTypeNode, write); - emitConstructor(node, name, baseTypeNode, write); - emitMemberFunctions(node, write); - - let returnStmt = createReturnStatement(name); - write(returnStmt); - } - - function emitExtendsCall(node: ClassLikeDeclaration, name: Identifier, baseTypeNode: ExpressionWithTypeArguments, write: (node: Statement) => void): void { - if (!baseTypeNode) { - return; - } - - let extendsExpr = createExtendsHelperCall(name); - let extendsStmt = createExpressionStatement(extendsExpr); - write(extendsStmt); - } - - function emitConstructor(node: ClassLikeDeclaration, name: Identifier, baseTypeNode: ExpressionWithTypeArguments, write: (node: Statement) => void) { - let constructor = getFirstConstructorWithBody(node); - let parameters: ParameterDeclaration[] = constructor ? visitNodes(constructor.parameters, transformNode) : []; - let body = createBlock([]); - - if (constructor) { - emitNode(constructor, transformConstructor, body.statements, PipelineFlags.LexicalEnvironment); - } - else if (baseTypeNode) { - let superCall = createDefaultSuperCall(); - body.statements.push(superCall); - } - - let constructorFunc = createFunctionDeclaration2(name, parameters, body); - write(constructorFunc); - } - - function transformConstructor(constructor: ConstructorDeclaration, write: (node: Statement) => void) { - emitCaptureThisForNode(constructor, write); - emitDefaultValueAssignments(constructor, write); - emitRestParameter(constructor, write); - pipeNodes(constructor.body.statements, transformNode, write); - } - - function transformParameter(node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) { - if (isBindingPattern(node.name)) { - write(createParameter2( - getGeneratedNameForNode(node), - /*initializer*/ undefined, - /*location*/ node - )); - } - else if (node.initializer) { - write(createParameter2( - node.name, - /*initializer*/ undefined, - /*location*/ node - )); - } - else if (!node.dotDotDotToken) { - // rest parameters are elided, other parameters are included. - write(node); - } - } - - function emitDefaultValueAssignments(node: FunctionLikeDeclaration, write: (node: Statement) => void) { - if (!(node.transformFlags & (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)) { - emitDefaultValueAssignmentForBindingPattern(parameter, name, initializer, write); - } - else if (initializer) { - emitDefaultValueAssignmentForInitializer(parameter, name, initializer, write); - } - } - } - - function emitDefaultValueAssignmentForBindingPattern(parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression, write: (node: Statement) => void): void { - let tempName = 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 = createVariableDeclarationList([]); - transformBindingElement(parameter, tempName, varDecls.declarations, /*assignments*/ undefined); - - let varStmt = createVariableStatement2(varDecls); - startOnNewLine(varStmt); - write(varStmt); - } - else if (initializer) { - let initExpr = visitNode(initializer, transformNode); - let assignExpr = createAssignmentExpression(tempName, initExpr); - let assignStmt = createExpressionStatement(assignExpr); - startOnNewLine(assignStmt); - write(assignStmt); - } - } - - function transformBindingElement(target: BindingElement, value: Expression, declarations: VariableDeclaration[], assignments: Expression[]): void { - if (target.initializer) { - // Combine value and initializer - let initializer = visitNode(target.initializer, transformNode); - value = value ? createDefaultValueCheck(value, initializer, declarations, assignments) : initializer; - } - else if (!value) { - // Use 'void 0' in absence of value and initializer - value = 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(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(element, 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(element, createElementAccessExpression3(value, i), declarations, assignments); - } - else if (i === elements.length - 1) { - transformBindingElement(element, createSliceCall(value, i), declarations, assignments); - } - } - } - } - else { - appendAssignment(name, value, declarations, assignments); - } - } - - function appendAssignment(left: Identifier, right: Expression, declarations: VariableDeclaration[], assignments: Expression[]): void { - let varDecl = createVariableDeclaration2(left, assignments ? undefined : right); - declarations.push(varDecl); - - if (assignments) { - let assignExpr = createAssignmentExpression(left, right); - assignments.push(assignExpr); - } - } - - function ensureIdentifier(value: Expression, declarations: VariableDeclaration[], assignments: Expression[]) { - if (isIdentifier(value)) { - return value; - } - else { - let tempVar = createTempVariable(/*loopVariable*/ false); - appendAssignment(tempVar, value, declarations, assignments); - return tempVar; - } - } - - function createDefaultValueCheck(value: Expression, defaultValue: Expression, declarations: VariableDeclaration[], assignments: Expression[]) { - value = ensureIdentifier(value, declarations, assignments); - let equalityExpr = createStrictEqualityExpression(value, createVoidZeroExpression()); - let conditionalExpr = createConditionalExpression2(equalityExpr, defaultValue, value); - return conditionalExpr; - } - - function emitDefaultValueAssignmentForInitializer(parameter: ParameterDeclaration, name: Identifier, initializer: Expression, write: (node: Statement) => void): void { - name = cloneNode(name); - let equalityExpr = createStrictEqualityExpression(name, createVoidZeroExpression()); - let initExpr = visitNode(initializer, transformNode); - let assignExpr = createAssignmentExpression(name, initExpr); - let assignStmt = createExpressionStatement(assignExpr); - let trueStmt = createBlock([assignStmt]); - let ifStmt = createIfStatement(equalityExpr, trueStmt); - startOnNewLine(ifStmt); - write(ifStmt); - } - - function emitRestParameter(node: FunctionLikeDeclaration, write: (node: Statement) => void): void { - if (!(node.transformFlags & TransformFlags.SubtreeContainsRestParameter)) { - return; - } - - let restParam = lastOrUndefined(node.parameters); - if (!restParam.dotDotDotToken || restParam.flags & NodeFlags.GeneratedRest) { - return; - } - - let restIndex = node.parameters.length - 1; - let _i = createTempVariable(/*loopVariable*/ true); - let name = getDeclarationName(restParam); - let arrayExpr = createArrayLiteralExpression([]); - let paramVarDecl = createVariableDeclaration2(name, arrayExpr); - let paramVarDecls = createVariableDeclarationList([paramVarDecl]); - let paramVarStmt = createVariableStatement2(paramVarDecls); - startOnNewLine(paramVarStmt); - write(paramVarStmt); - - let restIndexExpr = createNumericLiteral2(restIndex); - let initializerVarDecl = createVariableDeclaration2(_i, restIndexExpr); - let initializerVarDecls = createVariableDeclarationList([initializerVarDecl]); - let argumentsName = createIdentifier("arguments"); - let lengthName = createIdentifier("length"); - let argumentsLengthExpr = createPropertyAccessExpression2(argumentsName, lengthName); - let conditionExpr = createBinaryExpression2(_i, SyntaxKind.LessThanToken, argumentsLengthExpr); - let incrementerExpr = createPostfixUnaryExpression(_i, SyntaxKind.PlusPlusToken); - let arrayOffsetExpr = restIndex === 0 ? _i : createBinaryExpression2(_i, SyntaxKind.MinusToken, restIndexExpr); - let arrayElementExpr = createElementAccessExpression2(name, arrayOffsetExpr); - let argumentsElementExpr = createElementAccessExpression2(argumentsName, _i); - let assignExpr = createAssignmentExpression(arrayElementExpr, argumentsElementExpr); - let assignStmt = createExpressionStatement(assignExpr); - startOnNewLine(assignStmt); - - let forBody = createBlock([assignStmt]); - let forStmt = createForStatement(initializerVarDecls, conditionExpr, incrementerExpr, forBody); - startOnNewLine(forStmt); - write(forStmt); - } - - function emitCaptureThisForNode(node: Node, write: (node: Statement) => void): void { - if (isArrowFunction(node) || !(node.transformFlags & TransformFlags.SubtreeCapturesLexicalThis)) { - return; - } - - let thisName = createIdentifier("_this"); - let thisExpr = createThisKeyword(); - let varDecl = createVariableDeclaration2(thisName, thisExpr); - let varDecls = createVariableDeclarationList([varDecl]); - let varStmt = createVariableStatement2(varDecls); - startOnNewLine(varStmt); - write(varStmt); - } - - function emitMemberFunctions(node: ClassLikeDeclaration, write: (node: Statement) => void): void { - for (let member of node.members) { - if (isSemicolonClassElement(member)) { - transformSemicolonClassElement(member, write); - } - else if (isMethodDeclaration(member)) { - transformMethodDeclaration(node, member, write); - } - else if (isGetAccessor(member) || isSetAccessor(member)) { - let accessors = getAllAccessorDeclarations(node.members, member); - if (member === accessors.firstAccessor) { - transformAccessorDeclaration(node, accessors, write); - } - } - } - } - - function transformSemicolonClassElement(member: SemicolonClassElement, write: (node: Statement) => void): void { - let stmt = createEmptyStatement(); - startOnNewLine(stmt); - write(stmt); - } - - function transformMethodDeclaration(node: ClassLikeDeclaration, member: MethodDeclaration, write: (node: Statement) => void): void { - let prefix = getClassMemberPrefix(node, member); - let propExpr = getMemberAccessForPropertyName(node, member); - let funcExpr = transformFunctionLikeExpressionToFunctionExpression(member, /*name*/ undefined, /*location*/ undefined); - let assignExpr = createAssignmentExpression(propExpr, funcExpr); - let assignStmt = createExpressionStatement(assignExpr, /*location*/ member); - startOnNewLine(assignStmt); - write(assignStmt); - } - - function transformAccessorDeclaration(node: ClassLikeDeclaration, accessors: AllAccessorDeclarations, write: (node: Statement) => void): void { - let firstAccessor = accessors.firstAccessor; - let prefix = getClassMemberPrefix(node, firstAccessor); - let name = getExpressionForPropertyName(firstAccessor); - let descriptorExpr = createObjectLiteralExpression2(); - if (accessors.getAccessor) { - let funcExpr = transformFunctionLikeExpressionToFunctionExpression(accessors.getAccessor, /*name*/ undefined, /*location*/ accessors.getAccessor); - let getName = createIdentifier("get"); - let getProp = createPropertyAssignment(getName, funcExpr); - startOnNewLine(getProp); - descriptorExpr.properties.push(getProp); - } - - if (accessors.setAccessor) { - let funcExpr = transformFunctionLikeExpressionToFunctionExpression(accessors.setAccessor, /*name*/ undefined, /*location*/ accessors.setAccessor); - let setName = createIdentifier("set"); - let setProp = createPropertyAssignment(setName, funcExpr); - startOnNewLine(setProp); - descriptorExpr.properties.push(setProp); - } - - let trueExpr = createTrueKeyword(); - let enumerableName = createIdentifier("enumerable"); - let enumerableProp = createPropertyAssignment(enumerableName, trueExpr) - startOnNewLine(enumerableProp); - descriptorExpr.properties.push(enumerableProp); - - let configurableName = createIdentifier("configurable"); - let configurableProp = createPropertyAssignment(configurableName, trueExpr); - startOnNewLine(configurableProp); - descriptorExpr.properties.push(configurableProp); - - let definePropertyExpr = createDefinePropertyCall(prefix, name, descriptorExpr); - let definePropertyStmt = createExpressionStatement(definePropertyExpr); - write(definePropertyStmt); - } - - function transformFunctionExpression(node: FunctionExpression, write: (node: Expression) => void): void { - write(transformFunctionLikeExpressionToFunctionExpression(node, node.name, /*location*/ node)); - } - - function transformFunctionLikeExpressionToFunctionExpression(node: FunctionLikeDeclaration, name: Identifier, location: TextRange): FunctionExpression { - let parameters = visitNodes(node.parameters, transformNode); - let statements: Statement[] = []; - emitNode(node, transformFunctionBody, statements, PipelineFlags.LexicalEnvironment); - return createFunctionExpression2(name, parameters, createBlock(statements), location); - } - - function transformFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void): void { - let parameters = visitNodes(node.parameters, transformNode); - let statements: Statement[] = []; - emitNode(node, transformFunctionBody, statements, PipelineFlags.LexicalEnvironment); - write(createFunctionDeclaration2(node.name, parameters, createBlock(statements), /*location*/ node)); - } - - function transformFunctionBody(node: FunctionLikeDeclaration, write: (node: Statement) => void) { - emitCaptureThisForNode(node, write); - emitDefaultValueAssignments(node, write); - emitRestParameter(node, write); - - let body = node.body; - if (isBlock(body)) { - pipeNodes(body.statements, transformNode, write); - } - else { - let expr = visitNode(body, transformNode); - if (expr) { - let returnStmt = createReturnStatement(expr); - if (!childNodeStartPositionIsOnSameLine(currentSourceFile, node, body)) { - startOnNewLine(returnStmt); - } - - write(returnStmt); - } - } - } - - function getExpressionForPropertyName(member: ClassElement): Expression { - let memberName = member.name; - if (isIdentifier(memberName)) { - return createStringLiteral(memberName.text); - } - else if (isComputedPropertyName(memberName)) { - return visitNode(memberName.expression, transformNode); - } - else { - return cloneNode(memberName); - } - } - - function getMemberAccessForPropertyName(node: ClassLikeDeclaration, member: ClassElement): LeftHandSideExpression { - let target = getClassMemberPrefix(node, member); - let memberName = member.name; - if (isIdentifier(memberName)) { - return createPropertyAccessExpression2(target, cloneNode(memberName)); - } - else if (isComputedPropertyName(memberName)) { - let expression = visitNode(memberName.expression, transformNode); - return createElementAccessExpression2(target, expression); - } - else { - return createElementAccessExpression2(target, cloneNode(memberName)); - } - } - - function transformThisKeyword(node: LeftHandSideExpression): LeftHandSideExpression { - let container = getThisContainer(transformer, /*includeArrowFunctions*/ true); - if (isArrowFunction(container)) { - let thisName = createIdentifier("_this"); - return thisName; - } - - return node; - } - - function transformInitialSuperCall(node: ExpressionStatement, write: (node: Statement) => void) { - let statement = createDefaultSuperCall(); - return write(statement); - } - - function createDefaultSuperCall() { - let superName = createIdentifier("_super"); - let thisExpr = createThisKeyword(); - let argumentsName = createIdentifier("arguments"); - let applyExpr = createApplyCall(superName, thisExpr, argumentsName); - let statement = createExpressionStatement(applyExpr); - 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 c79c95df071..52f5637a03d 100644 --- a/src/compiler/transforms/es6.ts +++ b/src/compiler/transforms/es6.ts @@ -1,1374 +1,1151 @@ -/// +/// /*@internal*/ namespace ts { - export function toES6(transformer: Transformer, statements: NodeArray) { - let { - accept, - visitNode, - visitNodes, - emitNode, - emitNodes, - pipeNode, - pipeNodes, + export function transformES6(node: SourceFile, transformer: Transformer): SourceFile { + if (node.transformFlags & TransformFlags.ContainsES6) { + return transformES6Worker(node, transformer); + } + + return node; + } + + function transformES6Worker(node: SourceFile, transformer: Transformer): SourceFile { + let { + startLexicalEnvironment, + endLexicalEnvironment, getParentNode, findAncestorNode, declareLocal, getGeneratedNameForNode, + createTempVariable, hoistVariableDeclaration, getDeclarationName, getClassMemberPrefix, + pushNode, + popNode, + pipeNode, + pipeNodes, + mapNode, + mapNodes, + flattenNode, + visitNode, + visitNodes, + visitStatement, + visitConciseBody, + visitFunctionBody, + visitModuleBody, + visitSourceFile, + accept, } = transformer; - - let resolver = transformer.getEmitResolver(); + let compilerOptions = transformer.getCompilerOptions(); let languageVersion = compilerOptions.target || ScriptTarget.ES3; - - let currentModuleDeclaration: ModuleDeclaration; - let currentClassLikeDeclaration: ClassLikeDeclaration; - let currentBaseTypeNode: ExpressionWithTypeArguments; - let currentConstructor: ConstructorDeclaration; - let currentParametersWithPropertyAssignments: ParameterDeclaration[]; - let currentInstancePropertyAssignments: PropertyDeclaration[]; - let currentEnumLocalName: Identifier; - let currentParameterIndex: number; + let resolver = transformer.getEmitResolver(); + let currentSourceFile = node; + return visitSourceFile(node, visitor); - return visitNodes(statements, transformNode, PipelineFlags.LexicalEnvironment); - /** - * 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(node: Node, write: (node: Node) => void): void { - // Debug.assert( - // !needsTransform(node, TransformFlags.ThisNodeNeedsTransformToES7), - // "Cannot transform node with post-ES7 syntax."); - - if (node.transformFlags & TransformFlags.ThisNodeNeedsTransformToES6) { - transformNodeWorker(node, write); + * 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 visitor(node: Node, write: (node: Node) => void): void { + if (!node) { + return; } - else if (node.transformFlags & TransformFlags.SubtreeNeedsTransformToES6) { - accept(node, transformNode, write); + + if (node.transformFlags & TransformFlags.ThisNodeIsES6) { + visitorWorker(node, write); + } + else if (node.transformFlags & TransformFlags.ContainsES6) { + write(accept(node, visitor)); } else { write(node); } } - - function transformModuleElement(node: Node, write: (node: Node) => void): void { - if (node.flags & NodeFlags.Export) { - transformNodeWorker(node, write); - } - else { - transformNode(node, write); - } - } - + /** - * Transforms a node from TypeScript to ES6. - * @param context Context information for the transform. - * @param node The node to transform. - */ - function transformNodeWorker(node: Node, write: (node: Node) => void): void { - // TypeScript ambient declarations are elided. - if (node.flags & NodeFlags.Ambient) { - return; - } - + * Transforms a node from ES6 to ES5. + * @param context Context information for the transform. + * @param node The node to transform. + */ + function visitorWorker(node: Node, write: (node: Node) => void): void { switch (node.kind) { - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.ConstKeyword: - case SyntaxKind.DeclareKeyword: - // TypeScript accessibility modifiers are elided. - return; - - 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. - return; - - case SyntaxKind.IndexSignature: - // TypeScript index signatures are elided. - return; - - case SyntaxKind.Decorator: - // TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration. - return; - - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - // TypeScript type-only declarations are elided - return; - - case SyntaxKind.PropertyDeclaration: - // TypeScript property declarations are elided. - return; - - 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; - 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(node, write); - + visitClassDeclaration(node, write); + break; + 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(node, write); - - case SyntaxKind.HeritageClause: - // This is a heritage clause with TypeScript syntax extensions. - // - // TypeScript heritage clause extensions include: - // - `implements` clause - return visitHeritageClause(node, write); - - case SyntaxKind.ExpressionWithTypeArguments: - // TypeScript supports type arguments on an expression in an `extends` heritage clause. - return visitExpressionWithTypeArguments(node, write); - - case SyntaxKind.MethodDeclaration: - // TypeScript method declarations may be 'async', and may have decorators, modifiers - // or type annotations. - return transformMethodDeclaration(node, write); - - case SyntaxKind.GetAccessor: - // Get Accessors can have TypeScript modifiers, decorators, and type annotations. - return transformGetAccessor(node, write); - - case SyntaxKind.SetAccessor: - // Set Accessors can have TypeScript modifiers, decorators, and type annotations. - return transformSetAccessor(node, write); - - case SyntaxKind.FunctionDeclaration: - // TypeScript function declarations may be 'async' - return transformFunctionDeclaration(node, write); - - case SyntaxKind.FunctionExpression: - // TypeScript function expressions may be 'async' - return transformFunctionExpression(node, write); - - case SyntaxKind.ArrowFunction: - // TypeScript arrow functions may be 'async' - return transformArrowFunction(node, write); - + visitClassExpression(node, write); + break; + 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(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(node, write); - - case SyntaxKind.AwaitExpression: - // TypeScript 'await' expressions must be transformed. - return transformAwaitExpression(node, write); - + visitParameter(node, write); + break; + + case SyntaxKind.FunctionDeclaration: + visitFunctionDeclaration(node, write); + break; + + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + visitFunctionExpression(node, write); + break; + case SyntaxKind.VariableStatement: - // TypeScript namespace exports for variable statements must be transformed. - return transformVariableStatement(node, write); - - case SyntaxKind.ModuleDeclaration: - // TypeScript namespace declarations must be transformed. - return transformModuleDeclaration(node, write); - - case SyntaxKind.ImportEqualsDeclaration: - case SyntaxKind.ExportAssignment: - // TODO(rbuckton): TypeScript extensions we're not yet transforming. - + visitVariableStatement(node, write); + break; + + case SyntaxKind.VariableDeclarationList: + visitVariableDeclarationList(node, write); + break; + + case SyntaxKind.ExpressionStatement: + visitExpressionStatement(node, write); + break; + + case SyntaxKind.ForOfStatement: + visitForOfStatement(node, write); + break; + + case SyntaxKind.ObjectLiteralExpression: + visitObjectLiteralExpression(node, write); + break; + + case SyntaxKind.ShorthandPropertyAssignment: + visitShorthandPropertyAssignment(node, write); + break; + + case SyntaxKind.ArrayLiteralExpression: + visitArrayLiteralExpression(node, write); + break; + + case SyntaxKind.CallExpression: + visitCallExpression(node, write); + break; + + case SyntaxKind.NewExpression: + visitNewExpression(node, write); + break; + + case SyntaxKind.BinaryExpression: + visitBinaryExpression(node, write); + break; + + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + visitTemplateLiteral(node, write); + break; + + case SyntaxKind.TaggedTemplateExpression: + visitTaggedTemplateExpression(node, write); + break; + + case SyntaxKind.TemplateExpression: + visitTemplateExpression(node, write); + break; + + case SyntaxKind.SuperKeyword: + visitSuperKeyword(node, write); + break; + + case SyntaxKind.ThisKeyword: + visitThisKeyword(node, write); + break; + default: - // Fall back to the default visit behavior as some part of this node's - // subtree requires a transformation. - return accept(node, transformNode, write); + Debug.fail("Encountered unhandled node kind when transforming ES6 syntax."); + write(accept(node, visitor)); + break; } } - - /** - * 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(node: ClassDeclaration, write: (node: Statement) => void) { - let savedCurrentBaseTypeNode = currentBaseTypeNode; - let savedCurrentClassLikeDeclaration = currentClassLikeDeclaration; - currentClassLikeDeclaration = node; - currentBaseTypeNode = getAndVisitClassExtendsHeritageClauseElement(node); - - let classMembers: ClassElement[] = []; - emitNode(node, emitConstructor, classMembers); - emitNodes(node.members, transformNode, classMembers); - - if (nodeIsDecorated(node)) { - // If the class has been decorated, we need to emit the class as part of a `let` declaration - // to avoid the pitfalls of the doubly-bound class name. - let classExpr = createClassExpression3(currentBaseTypeNode, classMembers); - let varStmt = createLetStatement(getDeclarationName(node), classExpr, /*location*/ node, isTopLevelNonDefaultExport(node)); - write(setOriginalNode(varStmt, node)); + + function visitClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void): void { + visitClassLikeDeclaration(node, write); + } + + function visitClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void): void { + visitClassLikeDeclaration(node, write); + } + + function visitClassLikeDeclaration(node: ClassLikeDeclaration, write: (node: Expression | Statement) => void): void { + let name = getDeclarationName(node); + let statements = flattenNode(node, emitClassBody); + let baseTypeNode = getClassExtendsHeritageClauseElement(node); + let functionParameters: ParameterDeclaration[] = []; + let functionArguments: Expression[] = []; + if (baseTypeNode) { + functionParameters.push(createParameter3("_super")); + functionArguments.push(visitNode(baseTypeNode.expression, visitor, isExpressionNode)); + } + + let classFunction = createFunctionExpression3(functionParameters, createBlock(statements)); + let classExpression = createCallExpression2(createParenthesizedExpression(classFunction), functionArguments); + + if (isClassDeclaration(node)) { + let classStatement = createVariableStatement3(name, classExpression, /*location*/ node); + startOnNewLine(classStatement); + write(classStatement); } else { - let exportFlags = isTopLevelExport(node) ? node.flags & (NodeFlags.Export | NodeFlags.Default) : undefined; - let classDecl = createClassDeclaration2(getDeclarationName(node), currentBaseTypeNode, classMembers, /*location*/ node, exportFlags); - write(setOriginalNode(classDecl, node)); + write(classExpression); } - - pipeNodes(getInitializedProperties(node, /*isStatic*/ true), transformPropertyDeclarationToStatement, write); - - transformDecoratorsOfMembers(node, /*isStatic*/ false, write); - transformDecoratorsOfMembers(node, /*isStatic*/ true, write); - transformDecoratorsOfConstructor(node, write); - - if (isNamespaceLevelExport(node)) { - write(createExpressionStatement(createAssignmentExpression(getModuleMemberName(node), getDeclarationName(node)))); - } - else if (isTopLevelDefaultExport(node) && nodeIsDecorated(node)) { - write(createExportDefaultStatement(getDeclarationName(node))); - } - - currentClassLikeDeclaration = savedCurrentClassLikeDeclaration; - currentBaseTypeNode = savedCurrentBaseTypeNode; } - - function transformClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void) { - let savedCurrentClassLikeDeclaration = currentClassLikeDeclaration; - let savedCurrentBaseTypeNode = currentBaseTypeNode; - currentClassLikeDeclaration = node; - currentBaseTypeNode = getAndVisitClassExtendsHeritageClauseElement(node); - - let classMembers: ClassElement[] = []; - emitNode(node, emitConstructor, classMembers); - emitNodes(node.members, transformNode, classMembers); - - let classExpr = createClassExpression2(getDeclarationName(node), currentBaseTypeNode, classMembers); - let staticPropertyAssignments = getInitializedProperties(node, /*isStatic*/ true); - if (staticPropertyAssignments) { - let expressions: Expression[] = []; - let tempVar = declareLocal(); - expressions.push(createAssignmentExpression(tempVar, classExpr)); - emitNodes(staticPropertyAssignments, transformPropertyDeclarationToExpression, expressions); - expressions.push(tempVar); - write(createParenthesizedExpression(inlineExpressions(expressions))); + + function emitClassBody(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + startLexicalEnvironment(); + emitExtendsHelperIfNeeded(node, write); + emitConstructor(node, write); + emitMemberFunctions(node, write); + write(createReturnStatement(getDeclarationName(node))); + endLexicalEnvironment(write); + } + + function emitExtendsHelperIfNeeded(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + if (getClassExtendsHeritageClauseElement(node)) { + let extendsExpr = createExtendsHelperCall(getDeclarationName(node)); + let extendsStmt = createExpressionStatement(extendsExpr); + startOnNewLine(extendsStmt); + write(extendsStmt); + } + } + + function emitConstructor(node: ClassLikeDeclaration, write: (node: Statement) => void): void { + let ctor = getFirstConstructorWithBody(node); + let parameters: ParameterDeclaration[]; + let statements: Statement[]; + if (ctor) { + parameters = visitNodes(ctor.parameters, visitor, isParameter); + statements = flattenNode(ctor, emitConstructorBody); } else { - write(classExpr); + parameters = []; + statements = []; + if (getClassExtendsHeritageClauseElement(node)) { + statements.push(createDefaultSuperCall()); + } } - - currentClassLikeDeclaration = savedCurrentClassLikeDeclaration; - currentBaseTypeNode = savedCurrentBaseTypeNode; + + let name = getDeclarationName(node); + let constructorFunction = createFunctionDeclaration2(name, parameters, createBlock(statements)); + startOnNewLine(constructorFunction); + write(constructorFunction); } - - function getAndVisitClassExtendsHeritageClauseElement(node: ClassLikeDeclaration) { - let heritageClauses = visitNodes(node.heritageClauses, visitHeritageClause); - let extendsClause = heritageClauses && firstOrUndefined(heritageClauses); - let baseTypeNode = extendsClause && firstOrUndefined(extendsClause.types); - return baseTypeNode; + + function emitConstructorBody(constructor: ConstructorDeclaration, write: (node: Statement) => void): void { + startLexicalEnvironment(); + emitCaptureThisForNodeIfNeeded(constructor, write); + emitDefaultValueAssignments(constructor, write); + emitRestParameter(constructor, write); + pipeNodes(constructor.body.statements, visitor, write); + endLexicalEnvironment(write); } - - function emitConstructor(node: ClassLikeDeclaration, write: (node: ClassElement) => void): void { - // 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 constructor = getFirstConstructorWithBody(node); - let parameterPropertyAssignments = constructor ? getParametersWithPropertyAssignments(constructor) : undefined; - let instancePropertyAssignments = getInitializedProperties(node, /*isStatic*/ false); - - // For target ES6 and above, if there is no property assignment - // do not emit constructor in class declaration. - if (!parameterPropertyAssignments && !instancePropertyAssignments) { - write(constructor); + + function visitParameter(node: ParameterDeclaration, write: (node: ParameterDeclaration) => void): void { + if (isBindingPattern(node.name)) { + write(createParameter2(getGeneratedNameForNode(node), /*initializer*/ undefined, /*location*/ node)); + } + else if (node.initializer) { + write(createParameter2(node.name, /*initializer*/ undefined, /*location*/ node)); + } + else if (!node.dotDotDotToken) { + // rest parameters are elided, other parameters are included. + write(node); + } + } + + function shouldEmitDefaultValueAssignments(node: FunctionLikeDeclaration) { + return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments); + } + + function emitDefaultValueAssignments(node: FunctionLikeDeclaration, write: (node: Statement) => void) { + if (!shouldEmitDefaultValueAssignments(node)) { return; } - - let parameters: ParameterDeclaration[] = []; - if (constructor) { - emitNodes(constructor.parameters, transformNode, parameters); - } - else if (currentBaseTypeNode) { - parameters.push(createRestParameter(createIdentifier("args"), /*location*/ undefined, NodeFlags.GeneratedRest)); - } - - let savedCurrentConstructor = currentConstructor; - let savedCurrentParametersWithPropertyAssignments = currentParametersWithPropertyAssignments; - let savedCurrentInstancePropertyAssignments = currentInstancePropertyAssignments; - - let statements: Statement[] = []; - emitNode(node, emitConstructorBody, statements, PipelineFlags.LexicalEnvironment) - write(createConstructor2(parameters, createBlock(statements), /*location*/ constructor)); - - currentConstructor = savedCurrentConstructor; - currentParametersWithPropertyAssignments = savedCurrentParametersWithPropertyAssignments; - currentInstancePropertyAssignments = savedCurrentInstancePropertyAssignments; - } - - function emitConstructorBody(node: ClassLikeDeclaration, write: (node: Statement) => void) { - let superCall: ExpressionStatement; - if (currentConstructor) { - if (currentBaseTypeNode) { - superCall = findInitialSuperCall(currentConstructor); - if (superCall) { - write(superCall); - } - } - - pipeNodes(currentParametersWithPropertyAssignments, emitParameterPropertyAssignment, write); - } - else if (currentBaseTypeNode) { - let callExpr = createCallExpression2(createSuperKeyword(), [createSpreadElementExpression(createIdentifier("args"))]); - write(startOnNewLine(createExpressionStatement(callExpr, /*location*/ undefined, NodeFlags.GeneratedSuper))); - } - - pipeNodes(currentInstancePropertyAssignments, transformPropertyDeclarationToStatement, write); - - if (currentConstructor) { - pipeNodes(skip(currentConstructor.body.statements, superCall ? 1 : 0), transformNode, write); - } - } - - function emitParameterPropertyAssignment(node: ParameterDeclaration, write: (node: Statement) => void) { - let name = cloneNode(node.name); - let propExpr = createPropertyAccessExpression2(createThisKeyword(), name); - let assignExpr = createAssignmentExpression(propExpr, name); - write(startOnNewLine(createExpressionStatement(assignExpr))); - } - - function visitHeritageClause(node: HeritageClause, write: (node: HeritageClause) => void) { - if (node.token === SyntaxKind.ExtendsKeyword) { - write(updateHeritageClause(node, take(visitNodes(node.types, visitExpressionWithTypeArguments), 1))); - } - } - - function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments, write: (node: ExpressionWithTypeArguments) => void) { - write(updateExpressionWithTypeArguments(node, visitNode(node.expression, transformNode), /*typeArguments*/ undefined)); - } - - function transformPropertyDeclarationToStatement(node: PropertyDeclaration, write: (node: Statement) => void): void { - transformPropertyDeclarationToExpressionOrStatement(node, undefined, write); - } - - function transformPropertyDeclarationToExpression(node: PropertyDeclaration, write: (node: Expression) => void): void { - transformPropertyDeclarationToExpressionOrStatement(node, write, undefined); - } - - function transformPropertyDeclarationToExpressionOrStatement(node: PropertyDeclaration, writeExpression: (node: Expression) => void, writeStatement: (node: Statement) => void): void { - let isStatic = (node.flags & NodeFlags.Static) !== 0; - let target = isStatic ? getDeclarationName(currentClassLikeDeclaration) : createThisKeyword(); - let left = createMemberAccessForPropertyName(target, transformPropertyName(node), /*location*/ node.name); - let initializer = visitNode(node.initializer, transformNode); - let assignExpr = createAssignmentExpression(left, initializer); - setTextRange(assignExpr, node); - if (writeExpression) { - writeExpression(assignExpr); - } - else { - writeStatement(createExpressionStatement(assignExpr)); - } - } - - // emitter.ts:4074 - function 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) { - if (!properties) { - properties = []; - } - - properties.push(member); - } - } - - return properties; - } - - function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ParameterDeclaration[] { - let parameters: ParameterDeclaration[]; + for (let parameter of node.parameters) { - if (isIdentifier(parameter.name) && parameter.flags & NodeFlags.AccessibilityModifier) { - if (!parameters) { - parameters = []; - } - - parameters.push(parameter); + 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)) { + emitDefaultValueAssignmentForBindingPattern(parameter, name, initializer, write); + } + else if (initializer) { + emitDefaultValueAssignmentForInitializer(parameter, name, initializer, write); } } - - return parameters; } - - function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement { - if (ctor.body) { - let statement = firstOrUndefined(ctor.body.statements); - if (isExpressionStatement(statement)) { - let expr = statement.expression; - if (isCallExpression(expr)) { - let func = expr.expression; - if (isSuperKeyword(func)) { - return statement; + + function emitDefaultValueAssignmentForBindingPattern(parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression, write: (node: Statement) => void): void { + let tempName = 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 declarations = flattenNode(parameter, emitParameterBindingElements); + let varDecls = createVariableDeclarationList(declarations); + let varStmt = createVariableStatement2(varDecls); + startOnNewLine(varStmt); + write(varStmt); + } + else if (initializer) { + let initExpr = visitNode(initializer, visitor, isExpressionNode); + let assignExpr = createAssignmentExpression(tempName, initExpr); + let assignStmt = createExpressionStatement(assignExpr); + startOnNewLine(assignStmt); + write(assignStmt); + } + } + + function emitParameterBindingElements(parameter: ParameterDeclaration, write: (node: VariableDeclaration) => void): void { + let tempName = getGeneratedNameForNode(parameter); + emitBindingElement(parameter, tempName, write); + } + + function emitBindingElement(target: BindingElement, value: Expression, write: (node: VariableDeclaration) => void): void { + if (target.initializer) { + // Combine value and initializer + let initializer = visitNode(target.initializer, visitor, isExpressionNode); + value = value ? createDefaultValueCheck(value, initializer, /*isVariableDeclarationList*/ true, write) : initializer; + } + else if (!value) { + // Use 'void 0' in absence of value and initializer + value = createVoidZeroExpression(); + } + + let name = target.name; + if (isBindingPattern(name)) { + const elements = name.elements; + const numElements = elements.length; + if (numElements !== 1) { + // For anything other than a single-element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. Additionally, if we have zero elements + // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, + // so in that case, we'll intentionally create that temporary. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, /*isVariableDeclarationList*/ true, write); + } + 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; + emitBindingElement(element, createPropertyOrElementAccessExpression(value, propName), write); + } + else if (element.kind !== SyntaxKind.OmittedExpression) { + if (!element.dotDotDotToken) { + // Rewrite element to a declaration that accesses array element at index i + emitBindingElement(element, createElementAccessExpression3(value, i), write); + } + else if (i === elements.length - 1) { + emitBindingElement(element, createSliceCall(value, i), write); } } } } - - return undefined; - } - - function transformMethodDeclaration(node: MethodDeclaration, write: (node: ClassElement) => void) { - if (!node.body || node.flags & NodeFlags.Abstract) { - // Abstract methods and method overloads are elided. - return; - } - - let name = transformPropertyName(node); - let parameters = visitNodes(node.parameters, transformNode); - let body = transformFunctionBody(node); - let staticFlag = node.flags & NodeFlags.Static; - write(createMethodDeclaration2(name, parameters, body, /*location*/ node, staticFlag)); - } - - function transformGetAccessor(node: GetAccessorDeclaration, write: (node: ClassElement) => void) { - if (node.flags & NodeFlags.Abstract) { - // Abstract accessors are elided. - return; - } - - let name = transformPropertyName(node); - let parameters = visitNodes(node.parameters, transformNode); - let body = visitNode(node.body, transformNode); - let staticFlag = node.flags & NodeFlags.Static; - write(createGetAccessor2(name, parameters, body, /*location*/ node, staticFlag)); - } - - function transformSetAccessor(node: SetAccessorDeclaration, write: (node: ClassElement) => void) { - if (node.flags & NodeFlags.Abstract) { - // Abstract accessors are elided. - return; - } - - let name = transformPropertyName(node); - let parameters = visitNodes(node.parameters, transformNode); - let body = visitNode(node.body, transformNode); - let staticFlag = node.flags & NodeFlags.Static; - write(createSetAccessor2(name, parameters, body, /*location*/ node, staticFlag)); - } - - function transformFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void) { - if (!node.body) { - // Function overloads are elided. - return; - } - - let thisNodeIsNamespaceExport = isNamespaceLevelExport(node); - let parameters = visitNodes(node.parameters, transformNode); - let body = transformFunctionBody(node); - let flags = !thisNodeIsNamespaceExport ? node.flags & (NodeFlags.Default | NodeFlags.Export) : undefined; - write(createFunctionDeclaration3(node.asteriskToken, node.name, parameters, body, /*location*/ node, flags)); - - if (thisNodeIsNamespaceExport) { - write(createExpressionStatement(createAssignmentExpression(getModuleMemberName(node), cloneNode(node.name)))); + else { + emitAssignment(name, value, /*isTempVariable*/ false, /*isVariableDeclarationList*/ true, write); } } - - function transformFunctionExpression(node: FunctionExpression, write: (node: FunctionExpression) => void) { - let parameters = visitNodes(node.parameters, transformNode); - let body = transformFunctionBody(node); - write(createFunctionExpression3(node.asteriskToken, node.name, parameters, body, /*location*/ node)); - } - - function transformArrowFunction(node: ArrowFunction, write: (node: ArrowFunction) => void) { - let parameters = visitNodes(node.parameters, transformNode); - let body = transformFunctionBody(node); - write(createArrowFunction2(parameters, body, /*location*/ node)); - } - - function transformFunctionBody(node: FunctionLikeDeclaration): Block | Expression { - return isAsyncFunctionLike(node) - ? transformAsyncFunctionBody(node) - : visitNode(node.body, transformNode, PipelineFlags.LexicalEnvironment); - } - - function transformAsyncFunctionBody(node: FunctionLikeDeclaration): Block | Expression { - let promiseConstructor = getEntityNameFromTypeNode(node.type); - let hasLexicalArguments = (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]; - // }); - // } - // - - let body = node.body; - let generatorBody: Block; - if (!isBlock(body)) { - let bodyExpr = visitNode(body, transformNode); - let returnStmt = createReturnStatement(bodyExpr); - generatorBody = createBlock([returnStmt]); + + function emitAssignment(left: Identifier, right: Expression, isTempVariable: boolean, isVariableDeclarationList: boolean, write: (node: Expression | VariableDeclaration) => void): void { + if (isVariableDeclarationList) { + write(createVariableDeclaration2(left, right)); } else { - generatorBody = visitNode(body, transformNode); + write(createAssignmentExpression(left, right)); } - - let callExpr = createAwaiterHelperCall(hasLexicalArguments, promiseConstructor, generatorBody); - if (isArrowFunction(node)) { - return callExpr; + } + + function ensureIdentifier(value: Expression, reuseIdentifierExpressions: boolean, isVariableDeclarationList: boolean, write: (node: Expression | VariableDeclaration) => void) { + if (isIdentifier(value) && reuseIdentifierExpressions) { + return value; } else { - return createBlock([createReturnStatement(callExpr)], /*location*/ body); - } - } - - function transformParameter(node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) { - let name = visitNode(node.name, transformNode); - let initializer = visitNode(node.initializer, transformNode); - let flags = node.flags & ~NodeFlags.AccessibilityModifier; - write(createParameter2(name, initializer, /*location*/ node, flags)); - } - - function transformVariableStatement(node: VariableStatement, write: (node: Statement) => void) { - pipeNode(node.declarationList, transformVariableDeclarationListToExpressionStatement, write); - } - - function transformVariableDeclarationListToExpressionStatement(node: VariableDeclarationList, write: (node: Statement) => void) { - let expressions = visitNodes(node.declarations, transformVariableDeclarationToExpression); - if (expressions.length) { - write(createExpressionStatement(inlineExpressions(expressions))); - } - } - - function transformVariableDeclarationToExpression(node: VariableDeclaration, write: (node: Expression) => void) { - if (!node.initializer) { - return; - } - - transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ true); - - let name = node.name; - if (isBindingPattern(name)) { - let expr = visitNode(name, transformBindingPatternToExpression); - let initializer = visitNode(node.initializer, transformNode); - let assignExpr = createAssignmentExpression(expr, initializer); - let parenExpr = createParenthesizedExpression(assignExpr); - write(parenExpr); - } - else { - let name = getModuleMemberName(node); - let initializer = visitNode(node.initializer, transformNode); - let assignExpr = createAssignmentExpression(name, initializer); - write(assignExpr); - } - } - - function transformBindingPatternToExpression(node: BindingPattern, write: (node: Expression) => void) { - switch (node.kind) { - case SyntaxKind.ObjectBindingPattern: - return transformObjectBindingPatternToExpression(node, write); - - case SyntaxKind.ArrayBindingPattern: - return transformArrayBindingPatternToExpression(node, write); - } - } - - function transformObjectBindingPatternToExpression(node: ObjectBindingPattern, write: (node: Expression) => void) { - let properties = visitNodes(node.elements, transformBindingElementToObjectLiteralElement); - write(createObjectLiteralExpression2(properties)); - } - - function transformArrayBindingPatternToExpression(node: ArrayBindingPattern, write: (node: Expression) => void) { - let elements = visitNodes(node.elements, transformBindingElementToExpression); - write(createArrayLiteralExpression(elements)); - } - - function transformBindingElementToObjectLiteralElement(node: BindingElement, write: (node: ObjectLiteralElement) => void) { - let propertyName = node.propertyName || node.name; - let expr = visitNode(node, transformBindingElementToExpression); - write(createPropertyAssignment(propertyName, expr)); - } - - function transformBindingElementToExpression(node: BindingElement, write: (node: Expression) => void) { - transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ false); - } - - function transformBindingElementToExpressionWithParenthesisIfNeeded(node: BindingElement, write: (node: Expression) => void, parenthesizeObjectLiteralAssignment?: boolean) { - let name = node.name; - let expr = isBindingPattern(name) - ? visitNode(name, transformBindingPatternToExpression) - : getModuleMemberName(node); - - let initializer = visitNode(node.initializer, transformNode); - if (initializer) { - expr = createAssignmentExpression(expr, initializer); - } - - if (parenthesizeObjectLiteralAssignment && isObjectBindingPattern(name)) { - expr = createParenthesizedExpression(expr); - } - else if (node.dotDotDotToken) { - expr = createSpreadElementExpression(expr); - } - - write(expr); - } - - function transformModuleDeclaration(node: ModuleDeclaration, write: (node: Statement) => void) { - if (!shouldEmitModuleDeclaration(node)) { - return; - } - - let savedCurrentModuleDeclaration = currentModuleDeclaration; - currentModuleDeclaration = node; - - let location = node; - if (!isModuleMergedWithClass(node)) { - write(createVariableStatement3(node.name, undefined, location, isTopLevelExport(node) ? NodeFlags.Export : undefined)); - location = undefined; - } - - let localName = getGeneratedNameForNode(node); - let localParam = createParameter2(localName); - - let body = node.body; - let moduleBody: Block; - if (isModuleBlock(body)) { - moduleBody = createBlock(visitNodes(body.statements, transformModuleElement, PipelineFlags.LexicalEnvironment)); - } - else { - let inner = visitNode(body, transformNode, PipelineFlags.StatementOrBlock); - moduleBody = isBlock(inner) ? inner : createBlock([inner]); - } - - let funcExpr = createFunctionExpression2(/*name*/ undefined, [localParam], moduleBody); - let parenExpr = createParenthesizedExpression(funcExpr); - let moduleMemberName = getModuleMemberName(node); - let moduleStorageObjExpr = createObjectLiteralExpression2(); - let moduleStorageInitExpr = createAssignmentExpression(moduleMemberName, moduleStorageObjExpr); - let moduleStorageExpr = createLogicalOrExpression(moduleMemberName, moduleStorageInitExpr); - let moduleParam: Expression = moduleStorageExpr; - if (isNamespaceLevelExport(node)) { - moduleParam = createAssignmentExpression(cloneNode(node.name), moduleStorageExpr); - } - - let callExpr = createCallExpression2(parenExpr, [moduleParam]); - let callStmt = createExpressionStatement(callExpr, location, NodeFlags.GeneratedNamespace); - write(setOriginalNode(callStmt, node)); - - currentModuleDeclaration = savedCurrentModuleDeclaration; - } - - function shouldEmitModuleDeclaration(node: ModuleDeclaration) { - return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); - } - - function isModuleMergedWithClass(node: ModuleDeclaration) { - return !!(resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass); - } - - function getExpressionForPropertyName(container: Declaration): Expression { - let name = container.name; - if (isIdentifier(name)) { - return createStringLiteral(name.text); - } - else if (isComputedPropertyName(name)) { - return getGeneratedNameForNode(name); - } - else { - return cloneNode(name); - } - } - - function transformPropertyName(container: ClassElement): PropertyName { - let name = container.name; - if (isComputedPropertyName(name)) { - let expression = visitNode(name.expression, transformNode); - if (nodeCanBeDecorated(container) && nodeIsDecorated(container)) { - let generatedName = getGeneratedNameForNode(name); - hoistVariableDeclaration(generatedName); - expression = createAssignmentExpression(generatedName, expression); + let temp = createTempVariable(TempFlags.Auto); + if (!isVariableDeclarationList) { + hoistVariableDeclaration(temp); } - - return updateComputedPropertyName(name, expression); - } - else { - return cloneNode(name); + + emitAssignment(temp, value, /*isTempVariable*/ true, isVariableDeclarationList, write); + return temp; } } - - function transformEnumDeclaration(node: EnumDeclaration, write: (node: Statement) => void) { - if (!shouldEmitEnumDeclaration(node)) { - // Const enum declarations may be elided. + + function createDefaultValueCheck(value: Expression, defaultValue: Expression, isVariableDeclarationList: boolean, write: (node: Expression | VariableDeclaration) => void): Expression { + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, isVariableDeclarationList, write); + let equalityExpr = createStrictEqualityExpression(value, createVoidZeroExpression()); + return createConditionalExpression2(equalityExpr, defaultValue, value); + } + + function emitDefaultValueAssignmentForInitializer(parameter: ParameterDeclaration, name: Identifier, initializer: Expression, write: (node: Statement) => void): void { + name = cloneNode(name); + let equalityExpr = createStrictEqualityExpression(name, createVoidZeroExpression()); + let initExpr = visitNode(initializer, visitor, isExpressionNode); + let assignExpr = createAssignmentExpression(name, initExpr); + let assignStmt = createExpressionStatement(assignExpr); + let trueStmt = createBlock([assignStmt]); + let ifStmt = createIfStatement(equalityExpr, trueStmt); + startOnNewLine(ifStmt); + write(ifStmt); + } + + function shouldEmitRestParameter(node: ParameterDeclaration) { + return node.dotDotDotToken && !(node.flags & NodeFlags.GeneratedRest); + } + + function emitRestParameter(node: FunctionLikeDeclaration, write: (node: Statement) => void): void { + let lastParam = lastOrUndefined(node.parameters); + if (!shouldEmitRestParameter(lastParam)) { return; } - - let savedCurrentEnumLocalName = currentEnumLocalName; - currentEnumLocalName = getGeneratedNameForNode(node); - - let location: TextRange = node; - if (!isNamespaceLevelExport(node)) { - write(createVariableStatement3(node.name, /*initializer*/ undefined, location, isTopLevelExport(node) ? NodeFlags.Export : undefined)); - location = undefined; - } - - let enumStatements: Statement[] = []; - emitNodes(node.members, emitEnumMember, enumStatements, undefined, isStatementNode); - - let enumBody = createBlock(enumStatements); - let localNameParam = createParameter2(currentEnumLocalName); - let enumDecl = createFunctionExpression2(/*name*/ undefined, [localNameParam], enumBody); - let parenExpr = createParenthesizedExpression(enumDecl); - let moduleMemberName = getModuleMemberName(node); - let enumStorageObjectExpr = createObjectLiteralExpression2(); - let enumStorageInitExpr = createAssignmentExpression(moduleMemberName, enumStorageObjectExpr); - let enumStorageExpr = createLogicalOrExpression(moduleMemberName, enumStorageInitExpr); - let callExpr = createCallExpression2(parenExpr, [enumStorageExpr]); - write(createExpressionStatement(callExpr, location)); - - if (isNamespaceLevelExport(node)) { - write(createVariableStatement3(node.name, moduleMemberName)); - } - - currentEnumLocalName = savedCurrentEnumLocalName; + + // var param = []; + let name = getDeclarationName(lastParam); + let restIndex = node.parameters.length - 1; + let paramVarStmt = createVariableStatement3(name, createArrayLiteralExpression([])); + startOnNewLine(paramVarStmt); + write(paramVarStmt); + + // for (var _i = restIndex; _i < arguments.length; _i++) { + let _i = createTempVariable(TempFlags._i); + let initializerVarDecls = createVariableDeclarationList2(_i, createNumericLiteral2(restIndex)); + let argumentsLength = createPropertyAccessExpression3(createIdentifier("arguments"), "length"); + let condition = createLessThanExpression(_i, argumentsLength); + let incrementer = createPostfixUnaryExpression(_i, SyntaxKind.PlusPlusToken); + + // param[_i - restIndex] = arguments[_i]; + let arrayOffset = restIndex === 0 ? _i : createSubtractExpression(_i, createNumericLiteral2(restIndex)); + let arrayElement = createElementAccessExpression2(name, arrayOffset); + let argumentsElement = createElementAccessExpression2(createIdentifier("arguments"), _i); + let assignExpr = createAssignmentExpression(arrayElement, argumentsElement); + let assignStmt = createExpressionStatement(assignExpr); + startOnNewLine(assignStmt); + + let forStmt = createForStatement(initializerVarDecls, condition, incrementer, createBlock([assignStmt])); + startOnNewLine(forStmt); + write(forStmt); } - - function emitEnumMember(node: EnumMember, write: (node: Statement) => void) { - let enumNameExpr = getExpressionForPropertyName(node); - let enumValueExpr = getEnumMemberDeclarationValue(node); - let enumNameElemExpr = createElementAccessExpression2(currentEnumLocalName, enumNameExpr); - let enumValueAssignExpr = createAssignmentExpression(enumNameElemExpr, enumValueExpr); - let enumValueElemExpr = createElementAccessExpression2(currentEnumLocalName, enumValueAssignExpr); - let enumNameAssignExpr = createAssignmentExpression(enumValueElemExpr, enumNameExpr); - write(createExpressionStatement(enumNameAssignExpr, /*location*/ node)); - } - - function getEnumMemberDeclarationValue(member: EnumMember): Expression { - let value = resolver.getConstantValue(member); - if (value !== undefined) { - return createNumericLiteral2(value); - } - else if (member.initializer) { - return visitNode(member.initializer, transformNode); - } - else { - return createVoidZeroExpression(); + + function emitCaptureThisForNodeIfNeeded(node: Node, write: (node: Statement) => void): void { + if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && !isArrowFunction(node)) { + let thisName = createIdentifier("_this"); + let thisExpr = createThisKeyword(); + let varStmt = createVariableStatement3(thisName, thisExpr); + startOnNewLine(varStmt); + write(varStmt); } } - - function shouldEmitEnumDeclaration(node: EnumDeclaration) { - return isConst(node) || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; - } - - function transformAwaitExpression(node: AwaitExpression, write: (node: Expression) => void) { - let expression = visitNode(node.expression, transformNode); - let yieldExpr = createYieldExpression(/*asteriskToken*/ undefined, expression, /*location*/ node); - if (needsParenthesisForAwaitExpressionAsYield(node)) { - write(createParenthesizedExpression(yieldExpr)); - } - else { - write(yieldExpr); - } - } - - function needsParenthesisForAwaitExpressionAsYield(node: AwaitExpression) { - let parentNode = getParentNode(); - if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { - return true; - } - else if (isConditionalExpression(parentNode) && parentNode.condition === node) { - return true; - } - - return false; - } - - function transformDecoratorsOfMembers(node: ClassLikeDeclaration, isStatic: boolean, statements: (node: Statement) => void) { + + function emitMemberFunctions(node: ClassLikeDeclaration, write: (node: Statement) => void): void { for (let member of node.members) { - // only emit members in the correct group - if (isStatic !== ((member.flags & NodeFlags.Static) !== 0)) { - continue; + if (isSemicolonClassElement(member)) { + visitSemicolonClassElement(member, write); } - - // skip members that cannot be decorated (such as the constructor) - // skip a member if it or any of its parameters are not decorated - if (!nodeCanBeDecorated(member) || !nodeOrChildIsDecorated(member)) { - continue; + else if (isMethodDeclaration(member)) { + visitMethodDeclaration(node, member, write); + } + else if (isGetAccessor(member) || isSetAccessor(member)) { + let accessors = getAllAccessorDeclarations(node.members, member); + if (member === accessors.firstAccessor) { + let receiver = getClassMemberPrefix(node, member); + emitAccessors(receiver, accessors, /*isStatement*/ true, write); + } } - - transformDecoratorsOfMember(node, member, statements); } } - - function transformDecoratorsOfConstructor(node: ClassLikeDeclaration, write: (node: Statement) => void) { - let decorators = node.decorators; - let constructor = getFirstConstructorWithBody(node); - let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated); - - // skip decoration of the constructor if neither it nor its parameters are decorated - if (!decorators && !hasDecoratedParameters) { - return; - } - - // Emit the call to __decorate. Given the class: - // - // @dec - // class C { - // } - // - // The emit for the class is: - // - // C = __decorate([dec], C); - // - - let decoratorExpressions: Expression[] = []; - emitNodes(decorators, transformDecoratorToExpression, decoratorExpressions); - emitNode(constructor, emitDecoratorsOfParameters, decoratorExpressions); - - if (compilerOptions.emitDecoratorMetadata) { - emitNode(node, emitSerializedTypeMetadata, decoratorExpressions); - } - - let name = getDeclarationName(node); - let callExpr = createDecorateHelperCall(decoratorExpressions, name); - let statement = createExpressionStatement(callExpr); - write(statement); + + function visitSemicolonClassElement(member: SemicolonClassElement, write: (node: Statement) => void): void { + let stmt = createEmptyStatement(); + startOnNewLine(stmt); + write(stmt); } - - function transformDecoratorToExpression(node: Decorator, write: (node: Expression) => void) { - return visitNode(node.expression, transformNode); - } - - function transformDecoratorsOfMember(node: ClassLikeDeclaration, member: ClassElement, write: (node: Statement) => void) { - let decorators: Decorator[]; - let parameters: ParameterDeclaration[]; - - // skip an accessor declaration if it is not the first accessor - if (isAccessor(member) && member.body) { - let accessors = getAllAccessorDeclarations(node.members, member); - if (member !== accessors.firstAccessor) { - return; - } - - // get the decorators from the first accessor with decorators - decorators = accessors.firstAccessor.decorators; - if (!decorators && accessors.secondAccessor) { - decorators = accessors.secondAccessor.decorators; - } - - // we only decorate parameters of the set accessor - parameters = accessors.setAccessor - ? accessors.setAccessor.parameters - : undefined; - } - else { - decorators = member.decorators; - - // we only decorate the parameters here if this is a method - if (isMethodDeclaration(member) && member.body) { - parameters = member.parameters; - } - } - - // Emit the call to __decorate. Given the following: - // - // class C { - // @dec method(@dec2 x) {} - // @dec get accessor() {} - // @dec prop; - // } - // - // The emit for a method is: - // - // Object.defineProperty(C.prototype, "method", - // __decorate([ - // dec, - // __param(0, dec2), - // __metadata("design:type", Function), - // __metadata("design:paramtypes", [Object]), - // __metadata("design:returntype", void 0) - // ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method"))); - // - // The emit for an accessor is: - // - // Object.defineProperty(C.prototype, "accessor", - // __decorate([ - // dec - // ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor"))); - // - // The emit for a property is: - // - // __decorate([ - // dec - // ], C.prototype, "prop"); - // - - let decoratorExpressions: Expression[] = []; - emitNodes(decorators, transformDecoratorToExpression, decoratorExpressions); - emitNodes(parameters, emitDecoratorsOfParameter, decoratorExpressions); - if (compilerOptions.emitDecoratorMetadata) { - emitNode(node, emitSerializedTypeMetadata, decoratorExpressions); - } - + + function visitMethodDeclaration(node: ClassLikeDeclaration, member: MethodDeclaration, write: (node: Statement) => void): void { let prefix = getClassMemberPrefix(node, member); - let memberName = getExpressionForPropertyName(member); - if (isPropertyDeclaration(member)) { - let decorateExpr = createDecorateHelperCall(decoratorExpressions, prefix, memberName); - let statement = createExpressionStatement(decorateExpr); + let propExpr = createMemberAccessForPropertyName(prefix, visitNode(member.name, visitor, isPropertyName)); + let funcExpr = transformFunctionLikeToExpression(member); + let assignExpr = createAssignmentExpression(propExpr, funcExpr); + let assignStmt = createExpressionStatement(assignExpr, /*location*/ member); + startOnNewLine(assignStmt); + write(assignStmt); + } + + function emitAccessors(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations, isStatement: boolean, write: (node: Expression | Statement) => void): void { + let property = accessors.firstAccessor; + let propertyName = visitNode(property.name, visitor, isPropertyName); + let expressionName = createExpressionForPropertyName(propertyName, /*location*/ property.name); + let getter = accessors.getAccessor && transformFunctionLikeToExpression(accessors.getAccessor, /*location*/ accessors.getAccessor); + let setter = accessors.setAccessor && transformFunctionLikeToExpression(accessors.setAccessor, /*location*/ accessors.setAccessor); + let defineCall = createDefinePropertyCall2(receiver, expressionName, getter, setter, /*location*/ property); + if (isStatement) { + let statement = createExpressionStatement(defineCall); + startOnNewLine(statement); write(statement); } else { - let descriptorExpr = createGetOwnPropertyDescriptorCall(prefix, memberName); - let decorateExpr = createDecorateHelperCall(decoratorExpressions, prefix, memberName, descriptorExpr); - let definePropertyExpr = createDefinePropertyCall(prefix, memberName, decorateExpr); - let statement = createExpressionStatement(definePropertyExpr); - write(statement); + write(defineCall); } } - - function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, write: (node: Expression) => void) { - pipeNodes(node.parameters, emitDecoratorsOfParameter, write); + + function visitFunctionExpression(node: FunctionExpression, write: (node: Expression) => void): void { + write(transformFunctionLikeToExpression(node, /*location*/ node, node.name)); } - - function emitDecoratorsOfParameter(node: ParameterDeclaration, write: (node: Expression) => void, offset?: number) { - let savedCurrentParameterIndex = currentParameterIndex; - currentParameterIndex = offset; - pipeNodes(node.decorators, emitDecoratorOfParameter, write); - currentParameterIndex = savedCurrentParameterIndex; + + function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location?: TextRange, name?: Identifier): FunctionExpression { + let parameters = visitNodes(node.parameters, visitor, isParameter); + let statements = flattenNode(node, emitFunctionBody); + return createFunctionExpression2(name, parameters, createBlock(statements), location); } - - function emitDecoratorOfParameter(node: Decorator, write: (node: Expression) => void) { - let decoratorExpr = visitNode(node.expression, transformNode); - write(createParamHelperCall(currentParameterIndex, decoratorExpr)); + + function visitFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void): void { + let parameters = visitNodes(node.parameters, visitor, isParameter); + let statements = flattenNode(node, emitFunctionBody); + write(createFunctionDeclaration2(node.name, parameters, createBlock(statements), /*location*/ node)); } - - function emitSerializedTypeMetadata(node: Declaration, write: (node: Expression) => void) { - if (shouldAppendTypeMetadata(node)) { - let typeExpr = serializeTypeOfNode(node); - let metadataExpr = createMetadataHelperCall("design:type", createArrowFunction2([], typeExpr)); - write(metadataExpr); - } - if (shouldAppendParamTypesMetadata(node)) { - let paramTypesExpr = serializeParameterTypesOfNode(node); - let metadataExpr = createMetadataHelperCall("design:paramtypes", createArrowFunction2([], paramTypesExpr)); - write(metadataExpr); - } - if (shouldAppendReturnTypeMetadata(node)) { - let returnTypeExpr = serializeReturnTypeOfNode(node); - let metadataExpr = createMetadataHelperCall("design:returntype", createArrowFunction2([], returnTypeExpr)); - write(metadataExpr); - } - } - - 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. - switch (node.kind) { - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.PropertyDeclaration: - return true; - } - - return false; - } - - 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. - switch (node.kind) { - case SyntaxKind.MethodDeclaration: - return true; - } - return false; - } - - 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. - switch (node.kind) { - case SyntaxKind.ClassDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.SetAccessor: - return true; - } - return false; - } - - function serializeTypeOfNode(node: Node): Expression { - if (isPropertyDeclaration(node) || isParameter(node) || isGetAccessor(node)) { - return serializeTypeNode(node.type); - } - else if (isSetAccessor(node)) { - return serializeTypeNode(getSetAccessorTypeAnnotationNode(node)); - } - else if (isClassLike(node) || isFunctionLike(node)) { - return createIdentifier("Function"); + + function emitFunctionBody(node: FunctionLikeDeclaration, write: (node: Statement) => void): void { + startLexicalEnvironment(); + emitCaptureThisForNodeIfNeeded(node, write); + emitDefaultValueAssignments(node, write); + emitRestParameter(node, write); + + let body = node.body; + if (isBlock(body)) { + pipeNodes(body.statements, visitor, write); } else { - return createVoidZeroExpression(); + let expr = visitNode(body, visitor, isExpressionNode); + if (expr) { + let returnStmt = createReturnStatement(expr); + if (!childNodeStartPositionIsOnSameLine(currentSourceFile, node, body)) { + startOnNewLine(returnStmt); + } + + write(returnStmt); + } + } + endLexicalEnvironment(write); + } + + function visitBinaryExpression(node: BinaryExpression, write: (node: Expression) => void): void { + // If we are here it is because this is a destructuring assignment. + if (isEmptyObjectLiteralOrArrayLiteral(node.left)) { + write(node.right); + } + else { + let expressions = flattenNode(node, emitDestructuringExpressions); + let expression = inlineExpressions(expressions); + let parentNode = getParentNode(); + if (!isExpressionStatement(parentNode) && !isParenthesizedExpression(parentNode)) { + expression = createParenthesizedExpression(expression); + } + write(expression); } } - - function serializeParameterTypesOfNode(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(elementType)); + + function emitDestructuringExpressions(node: BinaryExpression, write: (node: Expression) => void): void { + let target = node.left; + let value = node.right; + let parentNode = getParentNode(); + if (isExpressionStatement(parentNode)) { + emitDestructuringAssignment(target, value, write); + } + else { + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, /*isVariableDeclarationList*/ false, write); + emitDestructuringAssignment(target, value, write); + write(value); + } + } + + function emitDestructuringAssignment(target: Expression, value: Expression, write: (node: Expression) => void) { + if (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.EqualsToken) { + value = createDefaultValueCheck(value, (target).right, /*isVariableDeclarationList*/ false, write); + target = (target).left; + } + if (isObjectLiteralExpression(target)) { + emitObjectLiteralAssignment(target, value, write); + } + else if (isArrayLiteralExpression(target)) { + emitArrayLiteralAssignment(target, value, write); + } + else if (isIdentifier(target)) { + emitAssignment(target, value, /*isTempVariable*/ false, /*isVariableDeclarationList*/ false, write); + } + else { + Debug.fail(); + } + } + + function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression, write: (node: Expression) => void): void { + let properties = target.properties; + if (properties.length !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, /*isVariableDeclarationList*/ false, write); + } + + for (let p of properties) { + if (isPropertyAssignment(p) || isShorthandPropertyAssignment(p)) { + let propName = (p).name; + let expr = createPropertyOrElementAccessExpression(value, propName); + emitDestructuringAssignment((p).initializer || propName, expr, write); + } + } + } + + function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, write: (node: Expression) => void): void { + let elements = target.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(value, /*reuseIdentifierExpressions*/ true, /*isVariableDeclarationList*/ false, write); + } + + for (let i = 0; i < elements.length; i++) { + let e = elements[i]; + if (e.kind !== SyntaxKind.OmittedExpression) { + if (e.kind !== SyntaxKind.SpreadElementExpression) { + emitDestructuringAssignment(e, createElementAccessExpression3(value, i), write); + } + else if (i === elements.length - 1) { + emitDestructuringAssignment((e).expression, createSliceCall(value, i), write); + } + } + } + } + + function visitVariableStatement(node: VariableStatement, write: (node: Statement) => void): void { + // TODO(rbuckton): Do we need to handle this? Exports needs to be moved to a module transformer. + write(accept(node, visitor)); + } + + function visitVariableDeclarationList(node: VariableDeclarationList, write: (node: VariableDeclarationList) => void): void { + // TODO(rbuckton): let/const + let declarations = visitNodes(node.declarations, visitVariableDeclaration, isVariableDeclaration); + write(updateVariableDeclarationList(node, declarations)); + } + + function visitVariableDeclaration(node: VariableDeclaration, write: (node: VariableDeclaration) => void): void { + if (isBindingPattern(node.name)) { + emitBindingElement(node, node.initializer, write); + } + else { + // TODO(rbuckton): Is there any reason we should hit this branch? + write(accept(node, visitor)); + } + } + + function visitForOfStatement(node: ForOfStatement, write: (node: Statement) => void): void { + // The following ES6 code: + // + // for (let v of expr) { } + // + // should be emitted as + // + // for (let _i = 0, _a = expr; _i < _a.length; _i++) { + // let v = _a[_i]; + // } + // + // where _a and _i are temps emitted to capture the RHS and the counter, + // respectively. + // When the left hand side is an expression instead of a let declaration, + // the "let v" is not emitted. + // When the left hand side is a let/const, the v is renamed if there is + // another v in scope. + // Note that all assignments to the LHS are emitted in the body, including + // all destructuring. + // Note also that because an extra statement is needed to assign to the LHS, + // for-of bodies are always emitted as blocks. + + let expression = visitNode(node.expression, visitor, isExpressionNode); + + // In the case where the user wrote an identifier as the RHS, like this: + // + // for (let v of arr) { } + // + // we don't want to emit a temporary variable for the RHS, just use it directly. + + let rhsIsIdentifier = expression.kind === SyntaxKind.Identifier; + let counter = createTempVariable(TempFlags._i); + let rhsReference = rhsIsIdentifier ? expression : createTempVariable(TempFlags.Auto); + + // _i = 0 + let loopInitializer = createVariableDeclarationList([], /*location*/ node.expression); + loopInitializer.declarations.push(createVariableDeclaration2(counter, createNumericLiteral2(0), /*location*/ node.expression)); + if (!rhsIsIdentifier) { + // , _a = expr + loopInitializer.declarations.push(createVariableDeclaration2(rhsReference, expression, /*location*/ node.expression)); + } + + // _i < _a.length; + let loopCondition = createLessThanExpression(counter, createPropertyAccessExpression3(rhsReference, "length"), /*location*/ node.initializer); + + // _i++) + let loopIncrementer = createPostfixUnaryExpression(counter, SyntaxKind.PlusPlusToken, /*location*/ node.initializer); + + // Body + let loopBodyStatements: Statement[] = []; + + // Initialize LHS + // let v = _a[_i]; + let rhsIterationValue = createElementAccessExpression(rhsReference, counter); + let initializer = node.initializer; + if (isVariableDeclarationList(initializer)) { + let declarations: VariableDeclaration[] = []; + if (initializer.declarations.length > 0) { + let declaration = initializer.declarations[0]; + if (isBindingPattern(declaration.name)) { + // This works whether the declaration is a var, let, or const. + // It will use rhsIterationValue _a[_i] as the initializer. + pushNode(initializer); + pipeNode(declaration, visitVariableDeclaration, declarations); + popNode(); } else { - parameterTypeExpressions.push(serializeTypeOfNode(parameter)); + // The following call does not include the initializer, so we have + // to emit it separately. + declarations.push(createVariableDeclaration2(declaration.name, rhsIterationValue)); } } - } - - return createArrayLiteralExpression(parameterTypeExpressions); - } - - function serializeReturnTypeOfNode(node: Node): Expression { - if (isFunctionLike(node)) { - return serializeTypeNode(node.type); - } - - return undefined; - } - - function serializeTypeNode(node: TypeNode): Expression { - if (node === undefined) { - return createIdentifier("Object"); - } - - switch (node.kind) { - case SyntaxKind.VoidKeyword: - return createVoidZeroExpression(); - - case SyntaxKind.ParenthesizedType: - return serializeTypeNode((node).type); - - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - return createIdentifier("Function"); - - case SyntaxKind.ArrayType: - case SyntaxKind.TupleType: - return createIdentifier("Array"); - - case SyntaxKind.TypePredicate: - case SyntaxKind.BooleanKeyword: - return createIdentifier("Boolean") - - case SyntaxKind.StringKeyword: - case SyntaxKind.StringLiteral: - return createIdentifier("String"); - - case SyntaxKind.NumberKeyword: - return createIdentifier("Number"); - - case SyntaxKind.SymbolKeyword: - return languageVersion < ScriptTarget.ES6 - ? getGlobalSymbolNameWithFallback() - : createIdentifier("Symbol"); - - case SyntaxKind.TypeReference: - return serializeTypeReferenceNode(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 createIdentifier("Object"); - } - - /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ - function serializeTypeReferenceNode(node: TypeReferenceNode) { - Debug.fail("parent pointer"); - let location: Node = node.parent; - while (isDeclaration(location) || isTypeNode(location)) { - location = location.parent; - } - - // Clone the type name and parent it to a location outside of the current declaration. - let typeName = cloneEntityName(node.typeName); - typeName.parent = location; - - let result = resolver.getTypeReferenceSerializationKind(typeName); - switch (result) { - case TypeReferenceSerializationKind.Unknown: - let tempVar = declareLocal(); - let globalObjectName = createIdentifier("Object"); - let typeExpr = serializeEntityNameAsExpression(typeName, /*useFallback*/ true); - let cacheExpr = createAssignmentExpression(tempVar, typeExpr); - let typeOfExpr = createTypeOfExpression(createParenthesizedExpression(cacheExpr)); - let functionLiteral = createStringLiteral("function"); - let equalityExpr = createStrictEqualityExpression(typeOfExpr, functionLiteral); - let logicalAndExpr = createLogicalAndExpression(equalityExpr, tempVar); - let logicalOrExpr = createLogicalOrExpression(logicalAndExpr, globalObjectName); - return logicalOrExpr; - - case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - return serializeEntityNameAsExpression(typeName, /*useFallback*/ false); - - case TypeReferenceSerializationKind.VoidType: - return createVoidZeroExpression(); - - case TypeReferenceSerializationKind.BooleanType: - return createIdentifier("Boolean"); - - case TypeReferenceSerializationKind.NumberLikeType: - return createIdentifier("Number"); - - case TypeReferenceSerializationKind.StringLikeType: - return createIdentifier("String"); - - case TypeReferenceSerializationKind.ArrayLikeType: - return createIdentifier("Array"); - - case TypeReferenceSerializationKind.ESSymbolType: - return languageVersion < ScriptTarget.ES6 - ? getGlobalSymbolNameWithFallback() - : createIdentifier("Symbol"); - - case TypeReferenceSerializationKind.TypeWithCallSignature: - return createIdentifier("Function"); - - case TypeReferenceSerializationKind.ObjectType: - default: - break; - } - - return createIdentifier("Object"); - } - - function serializeEntityNameAsExpression(node: EntityName, useFallback: boolean): Expression { - switch (node.kind) { - case SyntaxKind.Identifier: - let name = cloneNode(node); - if (useFallback) { - let undefinedLiteral = createStringLiteral("undefined"); - let typeOfExpr = createTypeOfExpression(name); - let equalityExpr = createStrictInequalityExpression(typeOfExpr, undefinedLiteral); - let logicalAndExpr = createLogicalAndExpression(equalityExpr, name); - return logicalAndExpr; - } - - return name; - - case SyntaxKind.QualifiedName: - return serializeQualifiedNameAsExpression(node, useFallback); - } - } - - function serializeQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean): Expression { - let left: Expression - if (node.left.kind === SyntaxKind.Identifier) { - left = serializeEntityNameAsExpression(node.left, useFallback); - } - else if (useFallback) { - let tempVar = declareLocal(); - let pathExpr = serializeEntityNameAsExpression(node.left, /*useFallback*/ true); - let cacheExpr = createAssignmentExpression(tempVar, pathExpr); - left = createLogicalAndExpression(cacheExpr, tempVar); + else { + // It's an empty declaration list. This can only happen in an error case, if the user wrote + // for (let of []) {} + declarations.push(createVariableDeclaration2(createTempVariable(TempFlags.Auto), rhsIterationValue)); + } + + loopBodyStatements.push(createVariableStatement2(createVariableDeclarationList(declarations), /*location*/ node.initializer)); } else { - left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); + // Initializer is an expression. Emit the expression in the body, so that it's + // evaluated on every iteration. + let assignmentExpression: Expression = createAssignmentExpression(initializer, rhsIterationValue); + if (isDestructuringAssignment(assignmentExpression)) { + // This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause + // the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash. + assignmentExpression = mapNode(assignmentExpression, visitBinaryExpression); + } + + loopBodyStatements.push(createExpressionStatement(assignmentExpression, /*location*/ node.initializer)); } - - // we clone the node here to create a copy of the node with no position information - let right = cloneNode(node.right); - let propExpr = createPropertyAccessExpression2(left, right); - return propExpr; - } - - function getGlobalSymbolNameWithFallback(): Expression { - let globalSymbolName = createIdentifier("Symbol"); - let globalObjectName = createIdentifier("Object"); - let typeOfExpr = createTypeOfExpression(globalSymbolName); - let functionLiteral = createStringLiteral("function"); - let equalityExpr = createStrictEqualityExpression(typeOfExpr, functionLiteral); - let conditionalExpr = createConditionalExpression2(equalityExpr, globalSymbolName, globalObjectName); - return conditionalExpr; - } - - function isTopLevelExport(node: Node) { - return !!(node.flags & NodeFlags.Export) && isSourceFile(getParentNode()); - } - - function isTopLevelDefaultExport(node: Node) { - return isTopLevelExport(node) && !!(node.flags & NodeFlags.Default); - } - - function isTopLevelNonDefaultExport(node: Node) { - return isTopLevelExport(node) && !(node.flags & NodeFlags.Default); - } - - function isNamespaceLevelExport(node: Node) { - return !!(node.flags & NodeFlags.Export) && !isSourceFile(getParentNode()); - } - - function getContainingModule(): ModuleDeclaration { - return findAncestorNode(isModuleDeclaration); - } - - function getContainingModuleName(): Identifier { - let container = findAncestorNode(isModuleDeclaration); - return container ? getGeneratedNameForNode(container) : createIdentifier("exports"); - } - - function getModuleMemberName(node: Declaration): Expression { - let name = getDeclarationName(node); - Debug.assert(isIdentifier(name)); - - if (getCombinedNodeFlags(transformer) & NodeFlags.Export) { - let container = getContainingModuleName(); - let propExpr = createPropertyAccessExpression2(container, name); - return propExpr; + + let statement = node.statement; + if (isBlock(statement)) { + pipeNodes(statement.statements, visitor, loopBodyStatements); } - return name; + else { + pipeNode(statement, visitor, loopBodyStatements); + } + + write(createForStatement(loopInitializer, loopCondition, loopIncrementer, createBlock(loopBodyStatements), /*location*/ node)); + } + + function visitObjectLiteralExpression(node: ObjectLiteralExpression, write: (node: LeftHandSideExpression) => void): void { + // We are here because a ComputedPropertyName was used somewhere in the expression. + let properties = node.properties; + let numProperties = properties.length; + + // Find the first computed property. + // Everything until that point can be emitted as part of the initial object literal. + let numInitialNonComputedProperties = numProperties; + for (let i = 0, n = properties.length; i < n; i++) { + if (properties[i].name.kind === SyntaxKind.ComputedPropertyName) { + numInitialNonComputedProperties = i; + break; + } + } + + Debug.assert(numInitialNonComputedProperties !== numProperties); + + // For computed properties, we need to create a unique handle to the object + // literal so we can modify it without risking internal assignments tainting the object. + let temp = declareLocal(); + + // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. + let initialProperties = visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties); + + let expressions: Expression[] = []; + expressions.push(createAssignmentExpression(temp, createObjectLiteralExpression(initialProperties))) + pipeNodes(properties, (property, write) => emitObjectLiteralElementAsExpression(property, write, node, temp), expressions, numInitialNonComputedProperties); + expressions.push(temp); + + write(createParenthesizedExpression(inlineExpressions(expressions))); + } + + function emitObjectLiteralElementAsExpression(property: ObjectLiteralElement, write: (node: Expression) => void, node: ObjectLiteralExpression, receiver: Identifier): void { + if (isGetAccessor(property) || isSetAccessor(property)) { + let accessors = getAllAccessorDeclarations(node.properties, property); + if (property !== accessors.firstAccessor) { + return; + } + + emitAccessors(receiver, accessors, /*isStatement*/ false, write); + } + else { + let propertyName = visitNode(property.name, visitor, isPropertyName); + let qualifiedName = createMemberAccessForPropertyName(receiver, propertyName); + + let initializer: Expression; + if (isPropertyAssignment(property)) { + initializer = visitNode(property.initializer, visitor, isExpressionNode); + } + else if (isShorthandPropertyAssignment(property)) { + initializer = cloneNode(property.name); + } + else if (isMethodDeclaration(property)) { + initializer = transformFunctionLikeToExpression(property, /*location*/ property); + } + else { + Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind); + } + + write(createAssignmentExpression(qualifiedName, initializer)); + } + } + + function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment, write: (node: ObjectLiteralElement) => void): void { + let property = createPropertyAssignment(node.name, cloneNode(node.name), /*location*/ node); + write(property); + } + + function visitArrayLiteralExpression(node: ArrayLiteralExpression, write: (node: LeftHandSideExpression) => void): void { + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + if (forEach(node.elements, isSpreadElementExpression)) { + write(spreadElements(node.elements, /*needsUniqueCopy*/ true)); + } + else { + // We don't handle SuperKeyword here, so fall back. + write(accept(node, visitor)); + } + } + + function visitCallExpression(node: CallExpression, write: (node: LeftHandSideExpression) => void): void { + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + if (forEach(node.arguments, isSpreadElementExpression)) { + emitCallWithSpread(node, write); + } + else { + let expression = visitNode(node.expression, visitor, isExpressionNode); + let thisArg = mapNode(createThisKeyword(), visitThisKeyword); + let args = visitNodes(node.arguments, visitor, isExpressionNode); + let callCall = createCallCall(expression, thisArg, args, /*location*/ node); + write(callCall); + } + } + + function emitCallWithSpread(node: CallExpression, write: (node: LeftHandSideExpression) => void): void { + let callee = skipParenthesis(node.expression); + let expression = callee; + let target: Expression; + if (isPropertyAccessExpression(callee)) { + // Target will be emitted as "this" argument. + ({ target, expression } = getCallTarget(visitNode(callee.expression, visitor, isLeftHandSideExpression))); + expression = createPropertyAccessExpression2(expression, callee.name); + } + else if (isElementAccessExpression(callee)) { + // target will be emitted as "this" argument. + ({ target, expression } = getCallTarget(visitNode(callee.expression, visitor, isLeftHandSideExpression))); + expression = createElementAccessExpression2(expression, visitNode(callee.argumentExpression, visitor, isExpressionNode)); + } + else if (isSuperKeyword(callee)) { + target = mapNode(createThisKeyword(/*location*/ callee), visitThisKeyword); + expression = createIdentifier("_super"); + } + else { + target = createVoidZeroExpression(); + expression = visitNode(callee, visitor, isExpressionNode); + } + + let argumentsArray = spreadElements(node.arguments, /*needsUniqueCopy*/ false); + let applyCall = createApplyCall(expression, target, argumentsArray); + write(applyCall); + } + + function visitNewExpression(node: NewExpression, write: (node: LeftHandSideExpression) => void): void { + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + if (forEach(node.arguments, isSpreadElementExpression)) { + let { target, expression } = getCallTarget(visitNode(node.expression, visitor, isExpressionNode)); + let argumentsArray = spreadElements(node.arguments, /*needsUniqueCopy*/ false, createVoidZeroExpression()); + let bindApply = createApplyCall(createPropertyAccessExpression3(expression, "bind"), target, argumentsArray); + write(createNewExpression(createParenthesizedExpression(bindApply), /*typeArguments*/ undefined, [])); + return; + } + else { + // We have nothing to do for SuperKeyword, so fallback. + write(accept(node, visitor)); + } + } + + function skipParenthesis(node: Expression) { + while (isParenthesizedExpression(node) || isTypeAssertionExpression(node) || isAsExpression(node)) { + node = (node).expression; + } + return node; + } + + function getCallTarget(expression: Expression) { + let target: PrimaryExpression; + if (isIdentifier(expression) || isThisKeyword(expression) || isSuperKeyword(expression)) { + target = cloneNode(expression); + } + else { + target = declareLocal(); + expression = createParenthesizedExpression(createAssignmentExpression(target, expression)); + } + + return { target, expression }; + } + + function spreadElements(elements: Expression[], needsUniqueCopy: boolean, leadingExpression?: Expression) { + let segments: Expression[] = []; + if (leadingExpression) { + segments.push(leadingExpression); + } + + let length = elements.length; + let start = 0; + for (let i = 0; i < length; i++) { + let element = elements[i]; + if (isSpreadElementExpression(element)) { + if (i > start) { + segments.push(createArrayLiteralExpression(visitNodes(elements.slice(start, i), visitor, isExpressionNode))); + } + + segments.push(needsUniqueCopy ? createSliceCall(element.expression) : element.expression); + start = i + 1; + } + } + + if (start < length) { + segments.push(createArrayLiteralExpression(visitNodes(elements.slice(start, length), visitor, isExpressionNode))); + } + + if (segments.length === 1) { + return parenthesizeForAccess(segments[0]); + } + + // Rewrite using the pattern .concat(, , ...) + return createConcatCall(segments.shift(), segments); + } + + function visitTemplateLiteral(node: LiteralExpression, write: (node: LeftHandSideExpression) => void): void { + write(createStringLiteral(node.text)); + } + + function visitTaggedTemplateExpression(node: TaggedTemplateExpression, write: (node: LeftHandSideExpression) => void): void { + // Visit the tag expression + let tag = visitNode(node.tag, visitor, isExpressionNode); + + // Allocate storage for the template site object + let templateObj = declareLocal(); + let rawObj = createPropertyAccessExpression3(templateObj, "raw"); + + // Build up the template arguments and the raw and cooked strings for the template. + let templateArguments: Expression[] = [templateObj]; + let cookedStrings: Expression[] = []; + let rawStrings: Expression[] = []; + let template = node.template; + if (isNoSubstitutionTemplateLiteral(template)) { + cookedStrings.push(createStringLiteral(template.text)); + rawStrings.push(getRawLiteral(template)); + } + else { + cookedStrings.push(createStringLiteral(template.head.text)); + rawStrings.push(getRawLiteral(template.head)); + pushNode(template); + for (let templateSpan of template.templateSpans) { + cookedStrings.push(createStringLiteral(templateSpan.literal.text)); + rawStrings.push(getRawLiteral(templateSpan.literal)); + templateArguments.push(mapNode(templateSpan, visitExpressionOfTemplateSpan)); + } + popNode(); + } + + let cookedArray = createArrayLiteralExpression(cookedStrings); + let rawArray = createArrayLiteralExpression(rawStrings); + + let expressions: Expression[] = []; + expressions.push(createAssignmentExpression(templateObj, cookedArray)); + expressions.push(createAssignmentExpression(rawObj, rawArray)); + expressions.push(createCallExpression2(tag, templateArguments)); + write(createParenthesizedExpression(inlineExpressions(expressions))); + } + + function getRawLiteral(node: LiteralExpression) { + // Find original source text, since we need to emit the raw strings of the tagged template. + // The raw strings contain the (escaped) strings of what the user wrote. + // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". + let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + + // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), + // thus we need to remove those characters. + // First template piece starts with "`", others with "}" + // Last template piece ends with "`", others with "${" + let isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail; + text = text.substring(1, text.length - (isLast ? 1 : 2)); + + // Newline normalization: + // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's + // and LineTerminatorSequences are normalized to for both TV and TRV. + text = text.replace(/\r\n?/g, "\n"); + text = escapeString(text); + return createStringLiteral(text); + } + + function visitExpressionOfTemplateSpan(node: TemplateSpan, write: (node: Expression) => void): void { + write(visitNode(node.expression, visitor, isExpressionNode)); + } + + function visitTemplateExpression(node: TemplateExpression, write: (node: Expression) => void): void { + let expressions: Expression[] = []; + + if (shouldEmitTemplateHead(node)) { + pipeNode(node.head, visitTemplateLiteral, expressions); + } + + pipeNodes(node.templateSpans, emitTemplateSpan, expressions); + + let expression = reduceLeft(expressions, createAddExpression); + if (templateNeedsParens(node)) { + expression = createParenthesizedExpression(expression); + } + + write(expression); + } + + function emitTemplateSpan(node: TemplateSpan, write: (node: Expression) => void): void { + // Check if the expression has operands and binds its operands less closely than binary '+'. + // If it does, we need to wrap the expression in parentheses. Otherwise, something like + // `abc${ 1 << 2 }` + // becomes + // "abc" + 1 << 2 + "" + // which is really + // ("abc" + 1) << (2 + "") + // rather than + // "abc" + (1 << 2) + "" + let expression = visitNode(node.expression, visitor, isExpressionNode); + let needsParens = !isParenthesizedExpression(expression) + && comparePrecedenceToBinaryPlus(expression) !== Comparison.GreaterThan; + + if (needsParens) { + expression = createParenthesizedExpression(expression); + } + + write(expression); + + // Only emit if the literal is non-empty. + // The binary '+' operator is left-associative, so the first string concatenation + // with the head will force the result up to this point to be a string. + // Emitting a '+ ""' has no semantic effect for middles and tails. + if (node.literal.text.length !== 0) { + pipeNode(node.literal, visitTemplateLiteral, write); + } + } + + function shouldEmitTemplateHead(node: TemplateExpression) { + // If this expression has an empty head literal and the first template span has a non-empty + // literal, then emitting the empty head literal is not necessary. + // `${ foo } and ${ bar }` + // can be emitted as + // foo + " and " + bar + // This is because it is only required that one of the first two operands in the emit + // output must be a string literal, so that the other operand and all following operands + // are forced into strings. + // + // If the first template span has an empty literal, then the head must still be emitted. + // `${ foo }${ bar }` + // must still be emitted as + // "" + foo + bar + + // There is always atleast one templateSpan in this code path, since + // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral() + Debug.assert(node.templateSpans.length !== 0); + + return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; + } + + function templateNeedsParens(template: TemplateExpression) { + let parentNode = getParentNode(); + if (isExpressionNode(parentNode)) { + switch (parentNode.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + return (parentNode).expression === template; + + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.ParenthesizedExpression: + return false; + + default: + return comparePrecedenceToBinaryPlus(parentNode) !== Comparison.LessThan; + } + } + + return false; + } + + function visitSuperKeyword(node: PrimaryExpression, write: (node: LeftHandSideExpression) => void): void { + let _super: LeftHandSideExpression = createIdentifier("_super"); + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.SuperInstance) { + _super = createPropertyAccessExpression3(createIdentifier("_super"), "prototype"); + } + + write(_super); + } + + function visitThisKeyword(node: PrimaryExpression, write: (node: LeftHandSideExpression) => void): void { + let container = getThisContainer(transformer, /*includeArrowFunctions*/ true); + if (isArrowFunction(container)) { + let thisName = createIdentifier("_this"); + write(thisName); + } + else { + write(node); + } + } + + function visitExpressionStatement(node: ExpressionStatement, write: (node: Statement) => void): void { + if (node.flags & NodeFlags.GeneratedSuper) { + write(createDefaultSuperCall()); + } + else { + // TODO(rbuckton): Is there any reason we should hit this branch? + write(accept(node, visitor)); + } + } + + function createDefaultSuperCall() { + let superName = createIdentifier("_super"); + let thisExpr = createThisKeyword(); + let argumentsName = createIdentifier("arguments"); + let applyExpr = createApplyCall(superName, thisExpr, argumentsName); + let statement = createExpressionStatement(applyExpr); + startOnNewLine(statement); + return statement; } } } \ No newline at end of file diff --git a/src/compiler/transforms/jsx.ts b/src/compiler/transforms/jsx.ts new file mode 100644 index 00000000000..c36b796a6d0 --- /dev/null +++ b/src/compiler/transforms/jsx.ts @@ -0,0 +1,511 @@ +/// +/*@internal*/ +namespace ts { + export function transformJsx(node: SourceFile, transformer: Transformer): SourceFile { + if (node.transformFlags & TransformFlags.ContainsJsx) { + return transformJsxWorker(node, transformer); + } + + return node; + } + + function transformJsxWorker(node: SourceFile, transformer: Transformer): SourceFile { + // create local aliases for transformer methods + let { + tryPushNode, + popNode, + pipeNode, + pipeNodes, + visitNode, + visitSourceFile, + accept, + } = transformer; + + return visitSourceFile(node, visitor); + + function visitor(node: Node, write: (node: Node) => void): void { + if (node.transformFlags & TransformFlags.Jsx) { + visitorWorker(node, write); + } + else if (node.transformFlags & TransformFlags.ContainsJsx) { + write(accept(node, visitor)); + } + else { + write(node); + } + } + + function visitorWorker(node: Node, write: (node: Node) => void): void { + switch (node.kind) { + case SyntaxKind.JsxElement: + visitJsxElement(node, write); + break; + + case SyntaxKind.JsxSelfClosingElement: + visitJsxSelfClosingElement(node, write); + break; + + case SyntaxKind.JsxText: + visitJsxText(node, write); + break; + + case SyntaxKind.JsxExpression: + visitJsxExpression(node, write); + break; + + default: + Debug.fail("Encountered unhandled node kind when transforming Jsx syntax."); + write(accept(node, visitor)); + break; + } + } + + function visitJsxElement(node: JsxElement, write: (node: Expression) => void): void { + emitJsxOpeningLikeElement(node.openingElement, node.children, write); + } + + function visitJsxSelfClosingElement(node: JsxSelfClosingElement, write: (node: Expression) => void): void { + emitJsxOpeningLikeElement(node, /*children*/ undefined, write); + } + + function emitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], write: (node: Expression) => void): void { + // We must the node onto the node stack if it is not already at the top. + let wasPushed = tryPushNode(node); + let tagName = getTagName(node); + let objectProperties: Expression; + if (node.attributes.length === 0) { + // When there are no attributes, React wants "null" + objectProperties = createNullKeyword(); + } + else { + // Either emit one big object literal (no spread attribs), or + // a call to React.__spread + let attrs = node.attributes; + let hasSpreadAttribute = forEach(attrs, isJsxSpreadAttribute); + if (hasSpreadAttribute) { + let segments: Expression[] = []; + let properties: ObjectLiteralElement[] = []; + for (let attr of attrs) { + if (isJsxSpreadAttribute(attr)) { + if (properties) { + segments.push(createObjectLiteralExpression(properties)); + properties = undefined; + } + + pipeNode(attr, emitJsxSpreadAttributeAsExpression, segments); + } + else { + if (!properties) { + properties = []; + } + + pipeNode(attr, emitJsxAttributeAsObjectLiteralElement, properties); + } + } + + if (properties) { + segments.push(createObjectLiteralExpression(properties)); + } + + objectProperties = createReactSpreadCall(segments); + } + else { + let properties: ObjectLiteralElement[] = []; + pipeNodes(node.attributes, emitJsxAttributeAsObjectLiteralElement, properties); + objectProperties = createObjectLiteralExpression(properties); + } + } + + if (wasPushed) { + popNode(); + } + + let childExpressions: Expression[] = []; + pipeNodes(children, emitJsxChildAsExpression, childExpressions); + + let reactCreateElementCall = createReactCreateElementCall(tagName, objectProperties, childExpressions); + write(reactCreateElementCall); + } + + function emitJsxSpreadAttributeAsExpression(node: JsxSpreadAttribute, write: (node: Expression) => void): void { + write(visitNode(node.expression, visitor, isExpressionNode)); + } + + function emitJsxAttributeAsObjectLiteralElement(node: JsxAttribute, write: (node: ObjectLiteralElement) => void): void { + let name = getAttributeName(node); + let expression = node.initializer + ? visitNode(node.initializer, visitor, isExpressionNode) + : createTrueKeyword(); + + write(createPropertyAssignment(name, expression)); + } + + function emitJsxChildAsExpression(node: JsxChild, write: (node: Expression) => void): void { + if (isJsxText(node)) { + pipeNode(node, emitNonEmptyJsxText, write); + } + else { + write(visitNode(node, visitor, isExpressionNode)); + } + } + + function emitNonEmptyJsxText(node: JsxText, write: (node: Expression) => void): void { + let text = getTextToEmit(node); + if (text !== undefined) { + write(createStringLiteral(text)); + } + } + + function getTextToEmit(node: JsxText) { + let text = trimReactWhitespaceAndApplyEntities(node); + if (text === undefined || text.length === 0) { + return undefined; + } + else { + return text; + } + } + + function trimReactWhitespaceAndApplyEntities(node: JsxText): string { + let result: string = undefined; + let text = getTextOfNode(node, /*includeTrivia*/ true); + let firstNonWhitespace = 0; + let lastNonWhitespace = -1; + + // JSX trims whitespace at the end and beginning of lines, except that the + // start/end of a tag is considered a start/end of a line only if that line is + // on the same line as the closing tag. See examples in tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx + for (let i = 0; i < text.length; i++) { + let c = text.charCodeAt(i); + if (isLineBreak(c)) { + if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) { + let part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1); + result = (result ? result + "\" + ' ' + \"" : "") + part; + } + firstNonWhitespace = -1; + } + else if (!isWhiteSpace(c)) { + lastNonWhitespace = i; + if (firstNonWhitespace === -1) { + firstNonWhitespace = i; + } + } + } + + if (firstNonWhitespace !== -1) { + let part = text.substr(firstNonWhitespace); + result = (result ? result + "\" + ' ' + \"" : "") + part; + } + + if (result) { + // Replace entities like   + result = result.replace(/&(\w+);/g, function(s: any, m: string) { + if (entities[m] !== undefined) { + return String.fromCharCode(entities[m]); + } + else { + return s; + } + }); + } + + return result; + } + + function getTagName(node: JsxElement | JsxOpeningLikeElement): Expression { + if (isJsxElement(node)) { + return getTagName(node.openingElement); + } + else { + let name = node.tagName; + if (isIdentifier(name) && isIntrinsicJsxName(name.text)) { + return createStringLiteral(name.text); + } + else { + return convertEntityNameToExpression(name); + } + } + } + + /** + * Emit an attribute name, which is quoted if it needs to be quoted. Because + * these emit into an object literal property name, we don't need to be worried + * about keywords, just non-identifier characters + */ + function getAttributeName(node: JsxAttribute): StringLiteral | Identifier { + let name = node.name; + if (/[A-Za-z_]+[\w*]/.test(name.text)) { + return createStringLiteral(name.text); + } + else { + return name; + } + } + + function visitJsxText(node: JsxText, write: (node: Node) => void): void { + let text = trimReactWhitespaceAndApplyEntities(node); + write(createStringLiteral(text || "")); + } + + function visitJsxExpression(node: JsxExpression, write: (node: Expression) => void): void { + let expression = visitNode((node).expression, visitor, isExpressionNode); + write(expression); + } + } + + var entities: Map = { + "quot": 0x0022, + "amp": 0x0026, + "apos": 0x0027, + "lt": 0x003C, + "gt": 0x003E, + "nbsp": 0x00A0, + "iexcl": 0x00A1, + "cent": 0x00A2, + "pound": 0x00A3, + "curren": 0x00A4, + "yen": 0x00A5, + "brvbar": 0x00A6, + "sect": 0x00A7, + "uml": 0x00A8, + "copy": 0x00A9, + "ordf": 0x00AA, + "laquo": 0x00AB, + "not": 0x00AC, + "shy": 0x00AD, + "reg": 0x00AE, + "macr": 0x00AF, + "deg": 0x00B0, + "plusmn": 0x00B1, + "sup2": 0x00B2, + "sup3": 0x00B3, + "acute": 0x00B4, + "micro": 0x00B5, + "para": 0x00B6, + "middot": 0x00B7, + "cedil": 0x00B8, + "sup1": 0x00B9, + "ordm": 0x00BA, + "raquo": 0x00BB, + "frac14": 0x00BC, + "frac12": 0x00BD, + "frac34": 0x00BE, + "iquest": 0x00BF, + "Agrave": 0x00C0, + "Aacute": 0x00C1, + "Acirc": 0x00C2, + "Atilde": 0x00C3, + "Auml": 0x00C4, + "Aring": 0x00C5, + "AElig": 0x00C6, + "Ccedil": 0x00C7, + "Egrave": 0x00C8, + "Eacute": 0x00C9, + "Ecirc": 0x00CA, + "Euml": 0x00CB, + "Igrave": 0x00CC, + "Iacute": 0x00CD, + "Icirc": 0x00CE, + "Iuml": 0x00CF, + "ETH": 0x00D0, + "Ntilde": 0x00D1, + "Ograve": 0x00D2, + "Oacute": 0x00D3, + "Ocirc": 0x00D4, + "Otilde": 0x00D5, + "Ouml": 0x00D6, + "times": 0x00D7, + "Oslash": 0x00D8, + "Ugrave": 0x00D9, + "Uacute": 0x00DA, + "Ucirc": 0x00DB, + "Uuml": 0x00DC, + "Yacute": 0x00DD, + "THORN": 0x00DE, + "szlig": 0x00DF, + "agrave": 0x00E0, + "aacute": 0x00E1, + "acirc": 0x00E2, + "atilde": 0x00E3, + "auml": 0x00E4, + "aring": 0x00E5, + "aelig": 0x00E6, + "ccedil": 0x00E7, + "egrave": 0x00E8, + "eacute": 0x00E9, + "ecirc": 0x00EA, + "euml": 0x00EB, + "igrave": 0x00EC, + "iacute": 0x00ED, + "icirc": 0x00EE, + "iuml": 0x00EF, + "eth": 0x00F0, + "ntilde": 0x00F1, + "ograve": 0x00F2, + "oacute": 0x00F3, + "ocirc": 0x00F4, + "otilde": 0x00F5, + "ouml": 0x00F6, + "divide": 0x00F7, + "oslash": 0x00F8, + "ugrave": 0x00F9, + "uacute": 0x00FA, + "ucirc": 0x00FB, + "uuml": 0x00FC, + "yacute": 0x00FD, + "thorn": 0x00FE, + "yuml": 0x00FF, + "OElig": 0x0152, + "oelig": 0x0153, + "Scaron": 0x0160, + "scaron": 0x0161, + "Yuml": 0x0178, + "fnof": 0x0192, + "circ": 0x02C6, + "tilde": 0x02DC, + "Alpha": 0x0391, + "Beta": 0x0392, + "Gamma": 0x0393, + "Delta": 0x0394, + "Epsilon": 0x0395, + "Zeta": 0x0396, + "Eta": 0x0397, + "Theta": 0x0398, + "Iota": 0x0399, + "Kappa": 0x039A, + "Lambda": 0x039B, + "Mu": 0x039C, + "Nu": 0x039D, + "Xi": 0x039E, + "Omicron": 0x039F, + "Pi": 0x03A0, + "Rho": 0x03A1, + "Sigma": 0x03A3, + "Tau": 0x03A4, + "Upsilon": 0x03A5, + "Phi": 0x03A6, + "Chi": 0x03A7, + "Psi": 0x03A8, + "Omega": 0x03A9, + "alpha": 0x03B1, + "beta": 0x03B2, + "gamma": 0x03B3, + "delta": 0x03B4, + "epsilon": 0x03B5, + "zeta": 0x03B6, + "eta": 0x03B7, + "theta": 0x03B8, + "iota": 0x03B9, + "kappa": 0x03BA, + "lambda": 0x03BB, + "mu": 0x03BC, + "nu": 0x03BD, + "xi": 0x03BE, + "omicron": 0x03BF, + "pi": 0x03C0, + "rho": 0x03C1, + "sigmaf": 0x03C2, + "sigma": 0x03C3, + "tau": 0x03C4, + "upsilon": 0x03C5, + "phi": 0x03C6, + "chi": 0x03C7, + "psi": 0x03C8, + "omega": 0x03C9, + "thetasym": 0x03D1, + "upsih": 0x03D2, + "piv": 0x03D6, + "ensp": 0x2002, + "emsp": 0x2003, + "thinsp": 0x2009, + "zwnj": 0x200C, + "zwj": 0x200D, + "lrm": 0x200E, + "rlm": 0x200F, + "ndash": 0x2013, + "mdash": 0x2014, + "lsquo": 0x2018, + "rsquo": 0x2019, + "sbquo": 0x201A, + "ldquo": 0x201C, + "rdquo": 0x201D, + "bdquo": 0x201E, + "dagger": 0x2020, + "Dagger": 0x2021, + "bull": 0x2022, + "hellip": 0x2026, + "permil": 0x2030, + "prime": 0x2032, + "Prime": 0x2033, + "lsaquo": 0x2039, + "rsaquo": 0x203A, + "oline": 0x203E, + "frasl": 0x2044, + "euro": 0x20AC, + "image": 0x2111, + "weierp": 0x2118, + "real": 0x211C, + "trade": 0x2122, + "alefsym": 0x2135, + "larr": 0x2190, + "uarr": 0x2191, + "rarr": 0x2192, + "darr": 0x2193, + "harr": 0x2194, + "crarr": 0x21B5, + "lArr": 0x21D0, + "uArr": 0x21D1, + "rArr": 0x21D2, + "dArr": 0x21D3, + "hArr": 0x21D4, + "forall": 0x2200, + "part": 0x2202, + "exist": 0x2203, + "empty": 0x2205, + "nabla": 0x2207, + "isin": 0x2208, + "notin": 0x2209, + "ni": 0x220B, + "prod": 0x220F, + "sum": 0x2211, + "minus": 0x2212, + "lowast": 0x2217, + "radic": 0x221A, + "prop": 0x221D, + "infin": 0x221E, + "ang": 0x2220, + "and": 0x2227, + "or": 0x2228, + "cap": 0x2229, + "cup": 0x222A, + "int": 0x222B, + "there4": 0x2234, + "sim": 0x223C, + "cong": 0x2245, + "asymp": 0x2248, + "ne": 0x2260, + "equiv": 0x2261, + "le": 0x2264, + "ge": 0x2265, + "sub": 0x2282, + "sup": 0x2283, + "nsub": 0x2284, + "sube": 0x2286, + "supe": 0x2287, + "oplus": 0x2295, + "otimes": 0x2297, + "perp": 0x22A5, + "sdot": 0x22C5, + "lceil": 0x2308, + "rceil": 0x2309, + "lfloor": 0x230A, + "rfloor": 0x230B, + "lang": 0x2329, + "rang": 0x232A, + "loz": 0x25CA, + "spades": 0x2660, + "clubs": 0x2663, + "hearts": 0x2665, + "diams": 0x2666 + }; +} \ No newline at end of file diff --git a/src/compiler/transforms/ts.ts b/src/compiler/transforms/ts.ts new file mode 100644 index 00000000000..65051767b87 --- /dev/null +++ b/src/compiler/transforms/ts.ts @@ -0,0 +1,1639 @@ +/// +/*@internal*/ +namespace ts { + export function transformTypeScript(node: SourceFile, transformer: Transformer): SourceFile { + if (node.transformFlags & TransformFlags.ContainsTypeScript) { + return transformTypeScriptWorker(node, transformer); + } + + return node; + } + + function transformTypeScriptWorker(node: SourceFile, transformer: Transformer): SourceFile { + // create local aliases for transformer methods + let { + startLexicalEnvironment, + endLexicalEnvironment, + getParentNode, + pushNode, + popNode, + findAncestorNode, + declareLocal, + getGeneratedNameForNode, + hoistVariableDeclaration, + getDeclarationName, + getClassMemberPrefix, + pipeNode, + pipeNodes, + mapNode, + mapNodes, + visitNode, + visitNodes, + visitStatement, + visitConciseBody, + visitFunctionBody, + visitModuleBody, + visitSourceFile, + accept, + } = transformer; + + let resolver = transformer.getEmitResolver(); + let compilerOptions = transformer.getCompilerOptions(); + let languageVersion = compilerOptions.target || ScriptTarget.ES3; + let moduleKind = compilerOptions.module || ModuleKind.None; + let currentSourceFile = node; + let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; + let exportSpecifiers: Map; + let exportEquals: ExportAssignment; + let exportFunctionForFile: string; + + // Mark that we are about to visit a new lexical environment. + return visitSourceFile(node, visitor); + + /** + * 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 visitor(node: Node, write: (node: Node) => void): void { + if (node.transformFlags & TransformFlags.TypeScript) { + visitorWorker(node, write); + } + else if (node.transformFlags & TransformFlags.ContainsTypeScript) { + write(accept(node, visitor)); + } + else { + write(node); + } + } + + /** + * Transforms a node from TypeScript to ES6. + * @param context Context information for the transform. + * @param node The node to transform. + */ + function visitorWorker(node: Node, write: (node: Node) => void): void { + // TypeScript ambient declarations are elided. + if (node.flags & NodeFlags.Ambient) { + return; + } + + switch (node.kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.DeclareKeyword: + // TypeScript accessibility modifiers are elided. + break; + + 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. + break; + + case SyntaxKind.IndexSignature: + // TypeScript index signatures are elided. + break; + + case SyntaxKind.Decorator: + // TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration. + break; + + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + // TypeScript type-only declarations are elided + break; + + case SyntaxKind.PropertyDeclaration: + // TypeScript property declarations are elided. + break; + + case SyntaxKind.Constructor: + // TypeScript constructors are elided. The constructor of a class will be + // reordered to the start of the member list in `transformClassDeclaration`. + break; + + 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 + visitClassDeclaration(node, write); + break; + + 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 + visitClassExpression(node, write); + break; + + case SyntaxKind.HeritageClause: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause + visitHeritageClause(node, write); + break; + + case SyntaxKind.ExpressionWithTypeArguments: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. + visitExpressionWithTypeArguments(node, write); + break; + + case SyntaxKind.MethodDeclaration: + // TypeScript method declarations may be 'async', and may have decorators, modifiers + // or type annotations. + visitMethodDeclaration(node, write); + break; + + case SyntaxKind.GetAccessor: + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. + visitGetAccessor(node, write); + break; + + case SyntaxKind.SetAccessor: + // Set Accessors can have TypeScript modifiers, decorators, and type annotations. + visitSetAccessor(node, write); + break; + + case SyntaxKind.FunctionDeclaration: + // TypeScript function declarations may be 'async' + visitFunctionDeclaration(node, write); + break; + + case SyntaxKind.FunctionExpression: + // TypeScript function expressions may be 'async' + visitFunctionExpression(node, write); + break; + + case SyntaxKind.ArrowFunction: + // TypeScript arrow functions may be 'async' + visitArrowFunction(node, write); + break; + + 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 + visitParameter(node, write); + break; + + case SyntaxKind.TypeAssertionExpression: + // TypeScript type assertions are removed, but their subtrees are preserved. + write((node).expression); + break; + + case SyntaxKind.AsExpression: + // TypeScript `as` expressions are removed, but their subtrees are preserved. + write((node).expression); + break; + + case SyntaxKind.EnumDeclaration: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. + visitEnumDeclaration(node, write); + break; + + case SyntaxKind.AwaitExpression: + // TypeScript 'await' expressions must be transformed. + visitAwaitExpression(node, write); + break; + + case SyntaxKind.VariableStatement: + // TypeScript namespace exports for variable statements must be transformed. + visitVariableStatement(node, write); + break; + + case SyntaxKind.ModuleDeclaration: + // TypeScript namespace declarations must be transformed. + visitModuleDeclaration(node, write); + break; + + case SyntaxKind.ImportEqualsDeclaration: + // TypeScript namespace or external module import. + visitImportEqualsDeclaration(node, write); + break; + + default: + Debug.fail("Encountered unhandled node kind when transforming TypeScript syntax."); + write(accept(node, visitor)); + break; + } + } + + /** + * Transforms a class declaration with TypeScript syntax into compatible ES6. + * @param node The node to transform. + * @param write The callback to execute to write out the result. + * @remarks + * This function will only be called when one of the following conditions are met: + * - The class has decorators. + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + * - The class is an export in a TypeScript namespace. + */ + function visitClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void): void { + // Get the name of the class + let name = getDeclarationName(node); + + // Visit the base type node for the class. + let baseTypeNode = mapNode(getClassExtendsHeritageClauseElement(node), visitExpressionWithTypeArguments); + + // Create a synthetic constructor for the class (if necessary), and visit the members of the class. + let classMembers: ClassElement[] = []; + pipeNode(node, (node, write) => emitConstructor(node, write, baseTypeNode), classMembers); + pipeNodes(node.members, visitor, classMembers); + + // Create the declaration for the class. Classes with decorators are transformed into a class + // expression inside of a let declaration. + let classStatement: Statement; + if (nodeIsDecorated(node)) { + // ES6 classes doubly-bind the class name. This would break class decorators as any local + // references would instead point to the *undecorated* class. To avoid this, and preserve the + // expected runtime semantics for ES.next class decorators, we instead encode the class + // as an expression as part of a `let` declaration. This makes it so that the binding is singular. + // + // We may, in the future, need to enclose such a class in an IIFE to preserve the double-binding semantics. + // + // If the class is also default export, we must defer the export until after we have written the decorators. + let classFlags = isTopLevelNonDefaultExport(node) ? NodeFlags.Let | NodeFlags.Export : NodeFlags.Let; + let classExpression = createClassExpression3(baseTypeNode, classMembers); + classStatement = createVariableStatement3(name, classExpression, /*location*/ node, classFlags); + } + else { + let classFlags = node.flags & ~NodeFlags.AccessibilityModifier; + classStatement = createClassDeclaration2(name, baseTypeNode, classMembers, /*location*/ node, classFlags); + } + + // Set a pointer to the original node for the class statement and write the statement. + classStatement.original = node; + write(classStatement); + + // Emit static property assignment. Because classDeclaration is lexically evaluated, + // it is safe to emit static property assignment after classDeclaration + // From ES6 specification: + // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using + // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + let staticProperties = getInitializedProperties(node, /*isStatic*/ true); + pipeNodes(staticProperties, (member, write) => emitPropertyDeclarationStatement(member, write, node), write); + + // Write any decorators of the node. + pipeNodes(getDecoratedClassElements(node, /*isStatic*/ false), emitDecoratorsOfMember, write); + pipeNodes(getDecoratedClassElements(node, /*isStatic*/ true), emitDecoratorsOfMember, write); + pipeNode(node, emitDecoratorsOfConstructor, write); + + // If the class is exported as part of a TypeScript namespace, emit the namespace export. + // Otherwise, emit the default export for a decorated class that was the default export. + if (isNamespaceLevelExport(node)) { + emitNamespaceExport(name, name, write); + } + else if (isTopLevelDefaultExport(node) && nodeIsDecorated(node)) { + emitDefaultExport(name, write); + } + } + + /** + * Transforms a class expression with TypeScript syntax into compatible ES6. + * @param node The node to transform. + * @param write The callback to execute to write out the result. + * @remarks + * This function will only be called when one of the following conditions are met: + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + */ + function visitClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void): void { + // Get the name of the class + let name = getDeclarationName(node); + + // Visit the base type node for the class. + let baseTypeNode = mapNode(getClassExtendsHeritageClauseElement(node), visitExpressionWithTypeArguments); + + // Create a synthetic constructor for the class (if necessary), and visit the members of the class. + let classMembers: ClassElement[] = []; + pipeNode(node, (node, write) => emitConstructor(node, write, baseTypeNode), classMembers); + pipeNodes(node.members, visitor, classMembers); + + // Create the new class expression. + let classExpression: LeftHandSideExpression = createClassExpression2(name, baseTypeNode, classMembers); + + // If the class has static properties, and it's a class expression, then we'll need + // to specialize the emit a bit. for a class expression of the form: + // + // class C { static a = 1; static b = 2; ... } + // + // We'll emit: + // + // (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp) + // + // This keeps the expression as an expression, while ensuring that the static parts + // of it have been initialized by the time it is used. + let staticProperties = getInitializedProperties(node, /*isStatic*/ true); + if (staticProperties) { + let expressions: Expression[] = []; + let temporaryStorage = declareLocal(); + expressions.push(createAssignmentExpression(temporaryStorage, classExpression)); + pipeNodes(staticProperties, (member, write) => emitPropertyDeclarationExpression(member, write, node, temporaryStorage), expressions); + expressions.push(temporaryStorage); + classExpression = createParenthesizedExpression(inlineExpressions(expressions)); + } + + write(classExpression); + } + + /** + * Transforms a HeritageClause with TypeScript syntax. + * @param node The HeritageClause to transform. + * @param write The callback to execute to write the result. + * @remarks + * This function will only be called when one of the following conditions are met: + * - The node is a non-`extends` heritage clause that should be elided. + * - The node is an `extends` heritage clause with more than one expression in `types`. + */ + function visitHeritageClause(node: HeritageClause, write: (node: HeritageClause) => void): void { + if (node.token === SyntaxKind.ExtendsKeyword) { + let types = mapNodes(node.types, visitExpressionWithTypeArguments, 0, 1); + write(updateHeritageClause(node, types)); + } + } + + /** + * Transforms an ExpressionWithTypeArguments with TypeScript syntax. + * @param node The ExpressionWithTypeArguments to transform. + * @param write The callback to execute to write the result. + * @remarks + * This function will only be called when one of the following conditions are met: + * - The node contains type arguments that should be elided. + */ + function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments, write: (node: ExpressionWithTypeArguments) => void): void { + let expression = visitNode(node.expression, visitor, isLeftHandSideExpression); + write(updateExpressionWithTypeArguments(node, expression, /*typeArguments*/ undefined)); + } + + /** + * Emits a synthesized constructor + * @param node The class for the synthesized constructor. + * @param write The callback to execute to write the synthesized constructor. + * @param baseTypeNode The node for the class extends clause, if present. + * @remarks This function is intended to support `transformClassLikeDeclaration` and should not be called otherwise. + */ + function emitConstructor(node: ClassLikeDeclaration, write: (node: ClassElement) => void, baseTypeNode: ExpressionWithTypeArguments): void { + // Check if we have property assignment inside class declaration. + // If there is a property assignment, we need to emit constructor whether users define it or not + // If there is no property assignment, we can omit constructor if users do not define it + let hasInstancePropertyWithInitializer = forEach(node.members, isInstancePropertyWithInitializer); + + let constructor = getFirstConstructorWithBody(node); + + // If the class does not contain nodes that require a synthesized constructor, + // accept the current constructor if it exists. + if (!hasInstancePropertyWithInitializer) { + if (constructor) { + write(accept(constructor, visitor)); + } + + return; + } + + // transform the parameters of the constructor + let parameters: ParameterDeclaration[]; + if (constructor) { + parameters = visitNodes(constructor.parameters, visitor, isParameter); + } + else if (baseTypeNode) { + parameters = [createRestParameter(createIdentifier("args"), /*location*/ undefined, NodeFlags.GeneratedRest)]; + } + + // transform the body of the constructor + let statements: Statement[] = []; + pipeNode(node, (_, write) => emitConstructorBody(node, write, constructor, baseTypeNode), statements); + + // write out the new constructor + write(startOnNewLine(createConstructor2(parameters, createBlock(statements), /*location*/ constructor))); + } + + /** + * Emits the body of the synthesized constructor. + * @param node The class for the synthesized constructor. + * @param write The callback to execute to write out statements of the body. + * @param constructor The existing constructor for the class, if present. + * @param baseTypeNode The node for the class extends clause, if present. + * @remarks This function is intended to be called from `emitConstructor` and should not be called otherwise. + */ + function emitConstructorBody(node: ClassLikeDeclaration, write: (node: Statement) => void, constructor: ConstructorDeclaration, baseTypeNode: ExpressionWithTypeArguments) { + startLexicalEnvironment(); + + // Emit the super call if it exists + let superCall = findInitialSuperCall(constructor); + if (constructor) { + let parameterPropertyAssignments = getParametersWithPropertyAssignments(constructor); + pushNode(constructor); + pipeNode(superCall, visitor, write); + pipeNodes(parameterPropertyAssignments, emitParameterPropertyAssignment, write); + popNode(); + } + else if (baseTypeNode) { + write(createSynthesizedSuperCall()); + } + + // pipe each property through a transformation + let properties = getInitializedProperties(node, /*isStatic*/ false); + pipeNodes(properties, (member, write) => emitPropertyDeclarationStatement(member, write, node), write); + + if (constructor) { + let statements = skip(constructor.body.statements, superCall ? 1 : 0); + pushNode(constructor); + pushNode(constructor.body); + pipeNodes(statements, visitor, write); + popNode(); + popNode(); + } + + endLexicalEnvironment(write); + } + + /** + * Emits a synthesized property assignment for a parameter declaration. + * @param node The parameter declaration. + * @param write The callback to execute to write the resulting assignment. + */ + function emitParameterPropertyAssignment(node: ParameterDeclaration, write: (node: Statement) => void): void { + let name = cloneNode(node.name); + let propExpr = createPropertyAccessExpression2(createThisKeyword(), name); + let assignExpr = createAssignmentExpression(propExpr, name); + write(startOnNewLine(createExpressionStatement(assignExpr))); + } + + /** + * Emits a synthetic assignment statement for a property declaration with an initializer. + * @param property The property declaration to emit. + * @param write The callback to execute to write the result. + * @param node The containing class for the property. + */ + function emitPropertyDeclarationStatement(property: PropertyDeclaration, write: (node: Statement) => void, node: ClassLikeDeclaration): void { + emitPropertyDeclarationWorker(node, property, /*receiver*/ undefined, /*isExpression*/ false, write); + } + + /** + * Emits a synthetic assignment expression for a property declaration with an initializer. + * @param property The property declaration to emit. + * @param write The callback to execute to write the result. + * @param node The containing class for the property. + */ + function emitPropertyDeclarationExpression(property: PropertyDeclaration, write: (node: Expression) => void, node: ClassLikeDeclaration, receiver: Identifier): void { + emitPropertyDeclarationWorker(node, property, receiver, /*isExpression*/ true, write); + } + + /** + * Emits a synthetic assignment for a property declaration with an initializer. + * @param node The containing class for the property. + * @param property The property declaration to emit. + * @param writeExpression The callback to execute to write the result as an expression. + * @param writeStatement The callback to execute to write the result as a statement. + */ + function emitPropertyDeclarationWorker(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression, isExpression: boolean, write: (node: Expression | Statement) => void): void { + let initializer = visitNode(property.initializer, visitor, isExpressionNode); + + if (!receiver) { + if (property.flags & NodeFlags.Static) { + receiver = getDeclarationName(node); + } + else { + receiver = createThisKeyword(); + } + } + + let left = createMemberAccessForPropertyName(receiver, getPropertyName(property), /*location*/ property.name); + let assignExpr = createAssignmentExpression(left, initializer); + if (isExpression) { + write(setTextRange(assignExpr, property)); + } + else { + write(setTextRange(createExpressionStatement(assignExpr), property)); + } + } + + function getDecoratedClassElements(node: ClassLikeDeclaration, isStatic: boolean): ClassElement[] { + let members: ClassElement[]; + for (let member of node.members) { + if (nodeCanBeDecorated(member) && nodeOrChildIsDecorated(member) && isStatic === ((member.flags & NodeFlags.Static) !== 0)) { + if (!members) { + members = []; + } + + members.push(member); + } + } + + return members; + } + + // emitter.ts:4074 + function isInstancePropertyWithInitializer(member: ClassElement) { + return isPropertyDeclaration(member) && !(member.flags & NodeFlags.Static) && !!member.initializer; + } + + function getInitializedProperties(node: ClassLikeDeclaration, isStatic: boolean): PropertyDeclaration[] { + let properties: PropertyDeclaration[]; + for (let member of node.members) { + if (isPropertyDeclaration(member) && isStatic === ((member.flags & NodeFlags.Static) !== 0) && member.initializer) { + if (!properties) { + properties = []; + } + + properties.push(member); + } + } + + return properties; + } + + function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ParameterDeclaration[] { + let parameters: ParameterDeclaration[]; + for (let parameter of node.parameters) { + if (isIdentifier(parameter.name) && parameter.flags & NodeFlags.AccessibilityModifier) { + if (!parameters) { + parameters = []; + } + + parameters.push(parameter); + } + } + + return parameters; + } + + function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement { + if (ctor && ctor.body) { + let statement = firstOrUndefined(ctor.body.statements); + if (isExpressionStatement(statement)) { + let expr = statement.expression; + if (isCallExpression(expr)) { + let func = expr.expression; + if (isSuperKeyword(func)) { + return statement; + } + } + } + } + + return undefined; + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked as abstract + * - The node is marked as async + * - The node has both a decorator and a computed property name + */ + function visitMethodDeclaration(node: MethodDeclaration, write: (node: ClassElement) => void) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return; + } + + let name = getPropertyName(node); + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = transformFunctionBody(node); + write(createMethodDeclaration2(name, parameters, body, /*location*/ node, node.flags & NodeFlags.Static)); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract + * - The node has both a decorator and a computed property name + */ + function visitGetAccessor(node: GetAccessorDeclaration, write: (node: ClassElement) => void) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return; + } + + let name = getPropertyName(node); + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = visitFunctionBody(node.body, visitor); + write(createGetAccessor2(name, parameters, body, /*location*/ node, node.flags & NodeFlags.Static)); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract + * - The node has both a decorator and a computed property name + */ + function visitSetAccessor(node: SetAccessorDeclaration, write: (node: ClassElement) => void) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return; + } + + let name = getPropertyName(node); + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = visitFunctionBody(node.body, visitor); + write(createSetAccessor2(name, parameters, body, /*location*/ node, node.flags & NodeFlags.Static)); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked async + * - The node is exported from a TypeScript namespace + */ + function visitFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return; + } + + let thisNodeIsNamespaceExport = isNamespaceLevelExport(node); + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = transformFunctionBody(node); + let flags = !thisNodeIsNamespaceExport ? node.flags & (NodeFlags.Default | NodeFlags.Export) : undefined; + write(createFunctionDeclaration3(node.asteriskToken, node.name, parameters, body, /*location*/ node, flags)); + + if (thisNodeIsNamespaceExport) { + let name = getDeclarationName(node); + emitNamespaceExport(name, name, write); + } + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked async + */ + function visitFunctionExpression(node: FunctionExpression, write: (node: FunctionExpression) => void) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return; + } + + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = transformFunctionBody(node); + write(createFunctionExpression4(node.asteriskToken, node.name, parameters, body, /*location*/ node)); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked async + */ + function visitArrowFunction(node: ArrowFunction, write: (node: ArrowFunction) => void) { + let parameters = visitNodes(node.parameters, visitor, isParameter); + let body = transformConciseBody(node); + write(createArrowFunction2(parameters, body, /*location*/ node)); + } + + function transformConciseBody(node: ArrowFunction): ConciseBody { + if (isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + + return visitConciseBody(node.body, visitor); + } + + function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody { + if (isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + + return visitFunctionBody(node.body, visitor); + } + + function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody { + let promiseConstructor = getEntityNameFromTypeNode(node.type); + let hasLexicalArguments = (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]; + // }); + // } + // + + let body = makeFunctionBody(visitConciseBody(node.body, visitor)); + let callExpr = createAwaiterHelperCall(hasLexicalArguments, promiseConstructor, body); + return isArrowFunction(node) ? callExpr : makeFunctionBody(callExpr); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node has an accessibility modifier. + */ + function visitParameter(node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) { + let name = visitNode(node.name, visitor, isBindingPatternOrIdentifier); + let initializer = visitNode(node.initializer, visitor, isExpressionNode); + let flags = node.flags & ~NodeFlags.AccessibilityModifier; + write(createParameter2(name, initializer, /*location*/ node, flags)); + } + + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is exported from a TypeScript namespace. + */ + function visitVariableStatement(node: VariableStatement, write: (node: Statement) => void) { + Debug.assert(isNamespaceLevelExport(node), "This function should only be called for namespace level exports."); + pipeNode(node.declarationList, transformVariableDeclarationListToExpressionStatement, write); + } + + /** + * @remarks + * This function is intended to be called from `transformVariableStatement` and should not be called otherwise. + */ + function transformVariableDeclarationListToExpressionStatement(node: VariableDeclarationList, write: (node: Statement) => void) { + let expressions = mapNodes(node.declarations, transformVariableDeclarationToExpression); + if (expressions.length) { + write(createExpressionStatement(inlineExpressions(expressions))); + } + } + + /** + * @remarks + * This function is intended to be called from `transformVariableDeclarationListToExpressionStatement` and should not be called otherwise. + */ + function transformVariableDeclarationToExpression(node: VariableDeclaration, write: (node: Expression) => void) { + if (!node.initializer) { + return; + } + + transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ true); + + let name = node.name; + if (isBindingPattern(name)) { + let expr = mapNode(name, transformBindingPatternToExpression); + let initializer = visitNode(node.initializer, visitor, isExpressionNode); + let assignExpr = createAssignmentExpression(expr, initializer); + let parenExpr = createParenthesizedExpression(assignExpr); + write(parenExpr); + } + else { + let qualifiedName = getModuleMemberName(name); + let initializer = visitNode(node.initializer, visitor, isExpressionNode); + let assignExpr = createAssignmentExpression(qualifiedName, initializer); + write(assignExpr); + } + } + + /** + * @remarks + * This function is intended to be called from `transformVariableDeclarationToExpression` and should not be called otherwise. + */ + function transformBindingPatternToExpression(node: BindingPattern, write: (node: Expression) => void) { + switch (node.kind) { + case SyntaxKind.ObjectBindingPattern: + return transformObjectBindingPatternToExpression(node, write); + + case SyntaxKind.ArrayBindingPattern: + return transformArrayBindingPatternToExpression(node, write); + } + } + + /** + * @remarks + * This function is intended to be called from `transformBindingPatternToExpression` and should not be called otherwise. + */ + function transformObjectBindingPatternToExpression(node: ObjectBindingPattern, write: (node: Expression) => void) { + let properties = mapNodes(node.elements, transformBindingElementToObjectLiteralElement); + write(createObjectLiteralExpression(properties)); + } + + /** + * @remarks + * This function is intended to be called from `transformBindingPatternToExpression` and should not be called otherwise. + */ + function transformArrayBindingPatternToExpression(node: ArrayBindingPattern, write: (node: Expression) => void) { + let elements = mapNodes(node.elements, transformBindingElementToExpression); + write(createArrayLiteralExpression(elements)); + } + + /** + * @remarks + * This function is intended to be called from `transformObjectBindingPatternToExpression` and should not be called otherwise. + */ + function transformBindingElementToObjectLiteralElement(node: BindingElement, write: (node: ObjectLiteralElement) => void) { + let propertyName = node.propertyName || node.name; + let expr = mapNode(node, transformBindingElementToExpression); + write(createPropertyAssignment(propertyName, expr)); + } + + /** + * @remarks + * This function is intended to be called from `transformArrayBindingPatternToExpression` or + * `transformBindingElementToObjectLiteralElement` and should not be called otherwise. + */ + function transformBindingElementToExpression(node: BindingElement, write: (node: Expression) => void) { + transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ false); + } + + /** + * @remarks + * This function is intended to be called from either `transformVariableDeclarationToExpression` or + * `transformBindingElementToExpression` and should not be called otherwise. + */ + function transformBindingElementToExpressionWithParenthesisIfNeeded(node: BindingElement, write: (node: Expression) => void, parenthesizeObjectLiteralAssignment?: boolean) { + let name = node.name; + let expr = isBindingPattern(name) + ? mapNode(name, transformBindingPatternToExpression) + : getModuleMemberName(name); + + let initializer = visitNode(node.initializer, visitor, isExpressionNode); + if (initializer) { + expr = createAssignmentExpression(expr, initializer); + } + + if (parenthesizeObjectLiteralAssignment && isObjectBindingPattern(name)) { + expr = createParenthesizedExpression(expr); + } + else if (node.dotDotDotToken) { + expr = createSpreadElementExpression(expr); + } + + write(expr); + } + + /** + * @remarks + * This function will be called any time a TypeScript namespace (ModuleDeclaration) is encountered. + */ + function visitModuleDeclaration(node: ModuleDeclaration, write: (node: Statement) => void) { + if (!shouldEmitModuleDeclaration(node)) { + return; + } + + let location = node; + if (!isModuleMergedWithClass(node)) { + write(createVariableStatement3(node.name, undefined, location, isTopLevelExport(node) ? NodeFlags.Export : undefined)); + location = undefined; + } + + let statements: Statement[] = []; + pipeNode(node.body, emitModuleBody, statements); + + let funcExpr = createFunctionExpression3([createParameter2(getGeneratedNameForNode(node))], createBlock(statements)); + let parenExpr = createParenthesizedExpression(funcExpr); + let moduleMemberName = getModuleMemberName(node.name); + let moduleStorageInitExpr = createAssignmentExpression(moduleMemberName, createObjectLiteralExpression([])); + let moduleStorageExpr = createLogicalOrExpression(moduleMemberName, moduleStorageInitExpr); + let moduleParam: Expression = moduleStorageExpr; + if (isNamespaceLevelExport(node)) { + moduleParam = createAssignmentExpression(cloneNode(node.name), moduleStorageExpr); + } + + let callExpr = createCallExpression2(parenExpr, [moduleParam]); + let callStmt = createExpressionStatement(callExpr, location, NodeFlags.GeneratedNamespace); + callStmt.original = node; + write(callStmt); + } + + function emitModuleBody(node: ModuleBody, write: (node: Statement) => void): void { + startLexicalEnvironment(); + if (isModuleBlock(node)) { + pipeNodes(node.statements, emitModuleElement, write); + } + else { + visitModuleDeclaration(node, write); + } + + endLexicalEnvironment(write); + } + + function emitModuleElement(node: Node, write: (node: Node) => void): void { + if (node.flags & NodeFlags.Export) { + visitorWorker(node, write); + } + else { + visitor(node, write); + } + } + + function shouldEmitModuleDeclaration(node: ModuleDeclaration) { + return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + } + + function isModuleMergedWithClass(node: ModuleDeclaration) { + return !!(resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass); + } + + function visitImportEqualsDeclaration(node: ImportEqualsDeclaration, write: (node: Statement) => void): void { + Debug.assert(!isExternalModuleImportEqualsDeclaration(node)); + + if (!shouldEmitImportEqualsDeclaration(node)) { + return; + } + + let name = getDeclarationName(node); + let moduleReference = convertEntityNameToExpression(visitNode(node.moduleReference, visitor, isEntityName)); + if (isNamespaceLevelExport(node)) { + emitNamespaceExport(node.name, moduleReference, write); + } + else { + let exportFlags = isTopLevelExport(node) ? NodeFlags.Export : undefined; + write(createVariableStatement3(name, moduleReference)); + } + } + + function shouldEmitImportEqualsDeclaration(node: ImportEqualsDeclaration) { + // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when + // - current file is not external module + // - import declaration is top level and target is value imported by entity name + return resolver.isReferencedAliasDeclaration(node) + || (!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node)); + } + + function getExpressionForPropertyName(container: Declaration): Expression { + let name = container.name; + if (isIdentifier(name)) { + return createStringLiteral(name.text); + } + else if (isComputedPropertyName(name)) { + return getGeneratedNameForNode(name); + } + else { + return cloneNode(name); + } + } + + function getPropertyName(container: ClassElement): PropertyName { + let name = container.name; + if (isComputedPropertyName(name)) { + let expression = visitNode(name.expression, visitor, isExpressionNode); + if (nodeCanBeDecorated(container) && nodeIsDecorated(container)) { + let generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + expression = createAssignmentExpression(generatedName, expression); + } + + return updateComputedPropertyName(name, expression); + } + else { + return cloneNode(name); + } + } + + /** + * @remarks + * This function will be called any time a TypeScript enum is encountered. + */ + function visitEnumDeclaration(node: EnumDeclaration, write: (node: Statement) => void) { + if (!shouldEmitEnumDeclaration(node)) { + // Const enum declarations may be elided. + return; + } + + let localName = getGeneratedNameForNode(node); + + let location: TextRange = node; + if (!isNamespaceLevelExport(node)) { + write(createVariableStatement3(node.name, /*initializer*/ undefined, location, isTopLevelExport(node) ? NodeFlags.Export : undefined)); + location = undefined; + } + + let enumStatements: Statement[] = []; + pipeNodes(node.members, emitEnumMember, enumStatements); + + let enumBody = createBlock(enumStatements); + let localNameParam = createParameter2(localName); + let enumDecl = createFunctionExpression2(/*name*/ undefined, [localNameParam], enumBody); + let parenExpr = createParenthesizedExpression(enumDecl); + let moduleMemberName = getModuleMemberName(node.name); + let enumStorageObjectExpr = createObjectLiteralExpression([]); + let enumStorageInitExpr = createAssignmentExpression(moduleMemberName, enumStorageObjectExpr); + let enumStorageExpr = createLogicalOrExpression(moduleMemberName, enumStorageInitExpr); + let callExpr = createCallExpression2(parenExpr, [enumStorageExpr]); + write(createExpressionStatement(callExpr, location)); + + if (isNamespaceLevelExport(node)) { + write(createVariableStatement3(node.name, moduleMemberName)); + } + } + + function emitEnumMember(node: EnumMember, write: (node: Statement) => void) { + let container = getParentNode(); + let localName = getGeneratedNameForNode(container); + let enumNameExpr = getExpressionForPropertyName(node); + let enumValueExpr = getEnumMemberDeclarationValue(node); + let enumNameElemExpr = createElementAccessExpression2(localName, enumNameExpr); + let enumValueAssignExpr = createAssignmentExpression(enumNameElemExpr, enumValueExpr); + let enumValueElemExpr = createElementAccessExpression2(localName, enumValueAssignExpr); + let enumNameAssignExpr = createAssignmentExpression(enumValueElemExpr, enumNameExpr); + write(createExpressionStatement(enumNameAssignExpr, /*location*/ node)); + } + + function getEnumMemberDeclarationValue(member: EnumMember): Expression { + let value = resolver.getConstantValue(member); + if (value !== undefined) { + return createNumericLiteral2(value); + } + else if (member.initializer) { + return visitNode(member.initializer, visitor, isExpressionNode); + } + else { + return createVoidZeroExpression(); + } + } + + function shouldEmitEnumDeclaration(node: EnumDeclaration) { + return isConst(node) || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; + } + + /** + * @remarks + * This function will be called any time a TypeScript await expression is encountered. + */ + function visitAwaitExpression(node: AwaitExpression, write: (node: Expression) => void) { + let expression = visitNode(node.expression, visitor, isExpressionNode); + let yieldExpr = createYieldExpression(/*asteriskToken*/ undefined, expression, /*location*/ node); + if (needsParenthesisForAwaitExpressionAsYield(node)) { + write(createParenthesizedExpression(yieldExpr)); + } + else { + write(yieldExpr); + } + } + + function needsParenthesisForAwaitExpressionAsYield(node: AwaitExpression) { + let parentNode = getParentNode(); + if (isBinaryExpression(parentNode) && !isAssignmentOperator(parentNode.operatorToken.kind)) { + return true; + } + else if (isConditionalExpression(parentNode) && parentNode.condition === node) { + return true; + } + + return false; + } + + function emitNamespaceExport(exportName: Identifier, exportValue: Expression, write: (node: Statement) => void): void { + let qualifiedName = getModuleMemberName(exportName); + write(createExpressionStatement(createAssignmentExpression(qualifiedName, exportValue))); + } + + function emitDefaultExport(exportValue: Expression, write: (node: Statement) => void): void { + let exportDefault = createExportDefaultStatement(exportValue); + write(exportDefault); + } + + function emitDecoratorsOfConstructor(node: ClassLikeDeclaration, write: (node: Statement) => void) { + let decorators = node.decorators; + let constructor = getFirstConstructorWithBody(node); + let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated); + + // skip decoration of the constructor if neither it nor its parameters are decorated + if (!decorators && !hasDecoratedParameters) { + return; + } + + // Emit the call to __decorate. Given the class: + // + // @dec + // class C { + // } + // + // The emit for the class is: + // + // C = __decorate([dec], C); + // + + let decoratorExpressions: Expression[] = []; + pipeNodes(decorators, emitDecoratorExpression, decoratorExpressions); + pipeNode(constructor, emitDecoratorsOfParameters, decoratorExpressions); + pipeNode(node, emitDecoratorTypeMetadata, decoratorExpressions); + + let name = getDeclarationName(node); + let decorateCall = createDecorateHelperCall(decoratorExpressions, name); + write(createExpressionStatement(decorateCall)); + } + + function emitDecoratorsOfMember(member: ClassElement, write: (node: Statement) => void) { + let container = getParentNode(); + let decorators: Decorator[]; + let method: FunctionLikeDeclaration; + + // skip an accessor declaration if it is not the first accessor + if (isAccessor(member) && member.body) { + let accessors = getAllAccessorDeclarations(container.members, member); + if (member !== accessors.firstAccessor) { + return; + } + + // get the decorators from the first accessor with decorators + decorators = accessors.firstAccessor.decorators; + if (!decorators && accessors.secondAccessor) { + decorators = accessors.secondAccessor.decorators; + } + + // we only decorate parameters of the set accessor + method = accessors.setAccessor; + } + else { + decorators = member.decorators; + + // we only decorate the parameters here if this is a method + if (isMethodDeclaration(member)) { + method = member; + } + } + + // Emit the call to __decorate. Given the following: + // + // class C { + // @dec method(@dec2 x) {} + // @dec get accessor() {} + // @dec prop; + // } + // + // The emit for a method is: + // + // Object.defineProperty(C.prototype, "method", + // __decorate([ + // dec, + // __param(0, dec2), + // __metadata("design:type", Function), + // __metadata("design:paramtypes", [Object]), + // __metadata("design:returntype", void 0) + // ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method"))); + // + // The emit for an accessor is: + // + // Object.defineProperty(C.prototype, "accessor", + // __decorate([ + // dec + // ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor"))); + // + // The emit for a property is: + // + // __decorate([ + // dec + // ], C.prototype, "prop"); + // + + let decoratorExpressions: Expression[] = []; + pipeNodes(decorators, emitDecoratorExpression, decoratorExpressions); + pipeNode(method, emitDecoratorsOfParameters, decoratorExpressions); + pipeNode(member, emitDecoratorTypeMetadata, decoratorExpressions); + + let prefix = getClassMemberPrefix(container, member); + let memberName = getExpressionForPropertyName(member); + if (isPropertyDeclaration(member)) { + let decorateCall = createDecorateHelperCall(decoratorExpressions, prefix, memberName); + write(createExpressionStatement(decorateCall)); + } + else { + let getOwnPropertyDescriptorCall = createGetOwnPropertyDescriptorCall(prefix, memberName); + let decorateCall = createDecorateHelperCall(decoratorExpressions, prefix, memberName, getOwnPropertyDescriptorCall); + let definePropertyCall = createDefinePropertyCall(prefix, memberName, decorateCall); + write(createExpressionStatement(definePropertyCall)); + } + } + + function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, write: (node: Expression) => void) { + for (var i = 0; i < node.parameters.length; i++) { + pipeNode(node.parameters[i], (parameter, write) => emitDecoratorsOfParameter(parameter, write, i), write); + } + } + + function emitDecoratorsOfParameter(node: ParameterDeclaration, write: (node: Expression) => void, parameterOffset: number) { + pipeNodes(node.decorators, (decorator, write) => emitDecoratorOfParameter(decorator, write, parameterOffset), write); + } + + function emitDecoratorOfParameter(node: Decorator, write: (node: Expression) => void, parameterOffset: number) { + let expression = visitNode(node.expression, visitor, isExpressionNode); + let paramCall = createParamHelperCall(parameterOffset, expression); + write(paramCall); + } + + function emitDecoratorExpression(node: Decorator, write: (node: Expression) => void) { + pipeNode(node.expression, visitor, write); + } + + function emitDecoratorTypeMetadata(node: Declaration, write: (node: Expression) => void) { + if (shouldAppendTypeMetadata(node)) { + let typeExpr = serializeTypeOfNode(node); + let metadataExpr = createMetadataHelperCall("design:type", createArrowFunction2([], typeExpr)); + write(metadataExpr); + } + if (shouldAppendParamTypesMetadata(node)) { + let paramTypesExpr = serializeParameterTypesOfNode(node); + let metadataExpr = createMetadataHelperCall("design:paramtypes", createArrowFunction2([], paramTypesExpr)); + write(metadataExpr); + } + if (shouldAppendReturnTypeMetadata(node)) { + let returnTypeExpr = serializeReturnTypeOfNode(node); + let metadataExpr = createMetadataHelperCall("design:returntype", createArrowFunction2([], returnTypeExpr)); + write(metadataExpr); + } + } + + function shouldAppendTypeMetadata(node: Declaration): boolean { + if (compilerOptions.emitDecoratorMetadata) { + // 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. + switch (node.kind) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + return true; + } + } + return false; + } + + function shouldAppendReturnTypeMetadata(node: Declaration): boolean { + if (compilerOptions.emitDecoratorMetadata) { + // 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. + switch (node.kind) { + case SyntaxKind.MethodDeclaration: + return true; + } + } + return false; + } + + function shouldAppendParamTypesMetadata(node: Declaration): boolean { + if (compilerOptions.emitDecoratorMetadata) { + // 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. + switch (node.kind) { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.SetAccessor: + return true; + } + } + return false; + } + + function serializeTypeOfNode(node: Node): Expression { + if (isPropertyDeclaration(node) || isParameter(node) || isGetAccessor(node)) { + return serializeTypeNode(node.type); + } + else if (isSetAccessor(node)) { + return serializeTypeNode(getSetAccessorTypeAnnotationNode(node)); + } + else if (isClassLike(node) || isFunctionLike(node)) { + return createIdentifier("Function"); + } + else { + return createVoidZeroExpression(); + } + } + + function serializeParameterTypesOfNode(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(elementType)); + } + else { + parameterTypeExpressions.push(serializeTypeOfNode(parameter)); + } + } + } + + return createArrayLiteralExpression(parameterTypeExpressions); + } + + function serializeReturnTypeOfNode(node: Node): Expression { + if (isFunctionLike(node)) { + return serializeTypeNode(node.type); + } + + return undefined; + } + + function serializeTypeNode(node: TypeNode): Expression { + if (node === undefined) { + return createIdentifier("Object"); + } + + switch (node.kind) { + case SyntaxKind.VoidKeyword: + return createVoidZeroExpression(); + + case SyntaxKind.ParenthesizedType: + return serializeTypeNode((node).type); + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return createIdentifier("Function"); + + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + return createIdentifier("Array"); + + case SyntaxKind.TypePredicate: + case SyntaxKind.BooleanKeyword: + return createIdentifier("Boolean") + + case SyntaxKind.StringKeyword: + case SyntaxKind.StringLiteral: + return createIdentifier("String"); + + case SyntaxKind.NumberKeyword: + return createIdentifier("Number"); + + case SyntaxKind.SymbolKeyword: + return languageVersion < ScriptTarget.ES6 + ? getGlobalSymbolNameWithFallback() + : createIdentifier("Symbol"); + + case SyntaxKind.TypeReference: + return serializeTypeReferenceNode(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 createIdentifier("Object"); + } + + /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ + function serializeTypeReferenceNode(node: TypeReferenceNode) { + Debug.fail("parent pointer"); + let location: Node = node.parent; + while (isDeclaration(location) || isTypeNode(location)) { + location = location.parent; + } + + // Clone the type name and parent it to a location outside of the current declaration. + let typeName = cloneEntityName(node.typeName); + typeName.parent = location; + + let result = resolver.getTypeReferenceSerializationKind(typeName); + switch (result) { + case TypeReferenceSerializationKind.Unknown: + let tempVar = declareLocal(); + let globalObjectName = createIdentifier("Object"); + let typeExpr = serializeEntityNameAsExpression(typeName, /*useFallback*/ true); + let cacheExpr = createAssignmentExpression(tempVar, typeExpr); + let typeOfExpr = createTypeOfExpression(createParenthesizedExpression(cacheExpr)); + let functionLiteral = createStringLiteral("function"); + let equalityExpr = createStrictEqualityExpression(typeOfExpr, functionLiteral); + let logicalAndExpr = createLogicalAndExpression(equalityExpr, tempVar); + let logicalOrExpr = createLogicalOrExpression(logicalAndExpr, globalObjectName); + return logicalOrExpr; + + case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: + return serializeEntityNameAsExpression(typeName, /*useFallback*/ false); + + case TypeReferenceSerializationKind.VoidType: + return createVoidZeroExpression(); + + case TypeReferenceSerializationKind.BooleanType: + return createIdentifier("Boolean"); + + case TypeReferenceSerializationKind.NumberLikeType: + return createIdentifier("Number"); + + case TypeReferenceSerializationKind.StringLikeType: + return createIdentifier("String"); + + case TypeReferenceSerializationKind.ArrayLikeType: + return createIdentifier("Array"); + + case TypeReferenceSerializationKind.ESSymbolType: + return languageVersion < ScriptTarget.ES6 + ? getGlobalSymbolNameWithFallback() + : createIdentifier("Symbol"); + + case TypeReferenceSerializationKind.TypeWithCallSignature: + return createIdentifier("Function"); + + case TypeReferenceSerializationKind.ObjectType: + default: + break; + } + + return createIdentifier("Object"); + } + + function serializeEntityNameAsExpression(node: EntityName, useFallback: boolean): Expression { + switch (node.kind) { + case SyntaxKind.Identifier: + let name = cloneNode(node); + if (useFallback) { + let undefinedLiteral = createStringLiteral("undefined"); + let typeOfExpr = createTypeOfExpression(name); + let equalityExpr = createStrictInequalityExpression(typeOfExpr, undefinedLiteral); + let logicalAndExpr = createLogicalAndExpression(equalityExpr, name); + return logicalAndExpr; + } + + return name; + + case SyntaxKind.QualifiedName: + return serializeQualifiedNameAsExpression(node, useFallback); + } + } + + function serializeQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean): Expression { + let left: Expression + if (node.left.kind === SyntaxKind.Identifier) { + left = serializeEntityNameAsExpression(node.left, useFallback); + } + else if (useFallback) { + let tempVar = declareLocal(); + let pathExpr = serializeEntityNameAsExpression(node.left, /*useFallback*/ true); + let cacheExpr = createAssignmentExpression(tempVar, pathExpr); + left = createLogicalAndExpression(cacheExpr, tempVar); + } + else { + left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); + } + + // we clone the node here to create a copy of the node with no position information + let right = cloneNode(node.right); + let propExpr = createPropertyAccessExpression2(left, right); + return propExpr; + } + + function getGlobalSymbolNameWithFallback(): Expression { + let globalSymbolName = createIdentifier("Symbol"); + let globalObjectName = createIdentifier("Object"); + let typeOfExpr = createTypeOfExpression(globalSymbolName); + let functionLiteral = createStringLiteral("function"); + let equalityExpr = createStrictEqualityExpression(typeOfExpr, functionLiteral); + let conditionalExpr = createConditionalExpression2(equalityExpr, globalSymbolName, globalObjectName); + return conditionalExpr; + } + + function isTopLevelExport(node: Node) { + return !!(node.flags & NodeFlags.Export) && isSourceFile(getParentNode()); + } + + function isTopLevelDefaultExport(node: Node) { + return isTopLevelExport(node) && !!(node.flags & NodeFlags.Default); + } + + function isTopLevelNonDefaultExport(node: Node) { + return isTopLevelExport(node) && !(node.flags & NodeFlags.Default); + } + + function isNamespaceLevelExport(node: Node) { + return !!(node.flags & NodeFlags.Export) && !isSourceFile(getParentNode()); + } + + function getContainingModule(): ModuleDeclaration { + return findAncestorNode(isModuleDeclaration); + } + + function getContainingModuleName(): Identifier { + let container = findAncestorNode(isModuleDeclaration); + return container ? getGeneratedNameForNode(container) : createIdentifier("exports"); + } + + function getModuleMemberName(name: Identifier): Expression { + name = makeSynthesized(name); + if (getCombinedNodeFlags(transformer) & NodeFlags.Export) { + let container = getContainingModuleName(); + let moduleName = createPropertyAccessExpression2(container, name); + return moduleName; + } + return name; + } + + function shouldEmitFunctionLikeDeclaration(node: FunctionLikeDeclaration) { + return !(!node.body || node.flags & (NodeFlags.Abstract | NodeFlags.Ambient)); + } + + function createSynthesizedSuperCall() { + let callExpr = createCallExpression2(createSuperKeyword(), [createSpreadElementExpression(createIdentifier("args"))]); + return startOnNewLine(createExpressionStatement(callExpr, /*location*/ undefined, NodeFlags.GeneratedSuper)); + } + } +} \ No newline at end of file diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5e977f1faef..1254118b6b9 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -321,7 +321,7 @@ namespace ts { bindTime = 0; checkTime = 0; emitTime = 0; - transform.transformTime = 0; + transformTime = 0; let program = createProgram(fileNames, compilerOptions, compilerHost); let exitStatus = compileProgram(); @@ -354,7 +354,7 @@ namespace ts { reportTimeStatistic("Parse time", programTime); reportTimeStatistic("Bind time", bindTime); reportTimeStatistic("Check time", checkTime); - reportTimeStatistic("Transform time", transform.transformTime); + reportTimeStatistic("Transform time", transformTime); reportTimeStatistic("Emit time", emitTime); reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); } @@ -363,7 +363,7 @@ namespace ts { function compileProgram(): ExitStatus { let diagnostics: Diagnostic[]; - + // First get and report any syntactic errors. diagnostics = program.getSyntacticDiagnostics(); @@ -560,7 +560,7 @@ namespace ts { return result; } } - + // declare var global: any, require: any; // if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') { // try { diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index cd9191c1b32..04677470a7d 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -19,9 +19,10 @@ "binder.ts", "checker.ts", "transform.ts", - "transform.generated.ts", + "transforms/module.ts", + "transforms/jsx.ts", + "transforms/ts.ts", "transforms/es6.ts", - "transforms/es5.ts", "emitter.ts", "program.ts", "commandLineParser.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f79e1075565..2bbb0ec066f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -328,6 +328,10 @@ namespace ts { JSDocTypeTag, JSDocTemplateTag, + // Raw nodes + RawExpression, + RawStatement, + // Synthesized list SyntaxList, // Enum value count @@ -425,185 +429,7 @@ namespace ts { // Used to know if we've computed data from children and cached it in this node. HasAggregatedChildData = 1 << 7 } - - /* @internal */ - export const enum TransformFlags { - // - // Individual Facts - // - - // A fact that states that a node is TypeScript syntax - TypeScript = 1 << 1, - ContainsTypeScript = 1 << 2, - ContainsTypeScriptClassSyntaxExtension = 1 << 3, - ContainsTypeScriptDecorator = 1 << 4, - ContainsTypeScriptModifier = 1 << 20, - - // A fact that states that a node is ES6 syntax - ES6 = 1 << 5, - ContainsES6 = 1 << 6, - ContainsES6Yield = 1 << 7, - ContainsES6ParameterBindingPattern = 1 << 8, - ContainsES6VariableBindingPattern = 1 << 9, - ContainsES6RestParameter = 1 << 10, - ContainsES6ParameterInitializer = 1 << 11, - ContainsES6SpreadElement = 1 << 12, - ContainsES6LetOrConst = 1 << 13, - ContainsES6ComputedPropertyName = 1 << 14, - - ContainsCapturedThis = 1 << 15, - ContainsLexicalThis = 1 << 16, - ContainsHoistedDeclaration = 1 << 17, - ContainsCompletionStatement = 1 << 18, - - LexicalEnvironment = 1 << 19, - // - // Assertions - // - - ThisNodeIsTypeScript = TypeScript | ContainsTypeScript, - ThisNodeIsTypeScriptModifier = ThisNodeIsTypeScript | ContainsTypeScriptModifier, - ThisNodeIsTypeScriptClassSyntaxExtension = ThisNodeIsTypeScript | ContainsTypeScriptClassSyntaxExtension, - ThisNodeIsTypeScriptDecorator = ThisNodeIsTypeScriptClassSyntaxExtension | ContainsTypeScriptDecorator, - - ThisNodeIsES6 = ES6 | ContainsES6, - ThisNodeIsES6Yield = ThisNodeIsES6 | ContainsES6Yield, - ThisNodeIsES6ParameterBindingPattern = ThisNodeIsES6 | ContainsES6ParameterBindingPattern, - ThisNodeIsES6VariableBindingPattern = ThisNodeIsES6 | ContainsES6VariableBindingPattern, - ThisNodeIsES6RestParameter = ThisNodeIsES6 | ContainsES6RestParameter, - ThisNodeIsES6ParameterInitializer = ThisNodeIsES6 | ContainsES6ParameterInitializer, - ThisNodeIsES6SpreadElement = ThisNodeIsES6 | ContainsES6SpreadElement, - ThisNodeIsES6LetOrConst = ThisNodeIsES6 | ContainsES6LetOrConst, - - // Additional markers - ThisNodeCapturesLexicalThis = ContainsCapturedThis, - ThisNodeIsThisKeyword = ContainsLexicalThis, - ThisNodeIsHoistedDeclaration = ContainsHoistedDeclaration, - ThisNodeIsCompletionStatement = ContainsCompletionStatement, - ThisNodeStartsNewLexicalEnvironment = LexicalEnvironment, - - // - // Masks - // - - ThisNodeIsTypeScriptMask = - TypeScript, - - ThisNodeIsES6Mask = - ES6, - - // - // Transformation Tests - // - - ThisNodeNeedsTransformToES6 = - ThisNodeIsTypeScriptMask, - - ThisNodeNeedsTransformToES5 = - ThisNodeIsES6Mask, - - // - // Queries - // - - SubtreeContainsTypeScript = - ThisNodeIsTypeScriptMask | - ContainsTypeScript, - - SubtreeNeedsTransformToES6 = - SubtreeContainsTypeScript, - - SubtreeContainsLexicalThis = - ContainsLexicalThis, - - SubtreeCapturesLexicalThis = - ContainsCapturedThis, - - SubtreeContainsRestParameter = - ContainsES6RestParameter, - - SubtreeContainsParameterBindingPattern = - ContainsES6ParameterBindingPattern, - - SubtreeContainsVariableBindingPattern = - ContainsES6VariableBindingPattern, - - SubtreeContainsParameterInitializer = - ContainsES6ParameterInitializer, - - SubtreeContainsES6 = - ThisNodeIsES6Mask | - ContainsES6, - - SubtreeNeedsTransformToES5 = - SubtreeContainsES6, - - SubtreeNeedsAnyTransform = - SubtreeNeedsTransformToES6 | - SubtreeNeedsTransformToES5, - - ThisParameterNeedsTransform = - ContainsES6VariableBindingPattern | - ContainsES6ParameterBindingPattern | - ContainsES6RestParameter | - ContainsES6ParameterInitializer, - - SubtreeContainsES6ParameterOrCapturedThis = - ContainsES6ParameterBindingPattern | - ContainsES6ParameterInitializer | - ContainsES6RestParameter | - ContainsCapturedThis, - - // - // Scope Exclusions - // - - NodeExcludes = - ThisNodeIsTypeScriptMask | - ThisNodeIsES6Mask, - - ParameterScopeExcludes = - ContainsTypeScriptModifier, - - ArrowFunctionScopeExcludes = - ContainsES6Yield | - ContainsES6VariableBindingPattern | - ContainsES6ParameterBindingPattern | - ContainsES6RestParameter | - ContainsES6ParameterInitializer | - ContainsES6LetOrConst | - ContainsHoistedDeclaration | - ContainsCompletionStatement | - ContainsLexicalThis, - - FunctionScopeExcludes = - ArrowFunctionScopeExcludes | - ContainsLexicalThis | - ContainsCapturedThis, - - ClassScopeExcludes = - ContainsLexicalThis | - ContainsCapturedThis | - ContainsES6VariableBindingPattern | - ContainsES6ParameterBindingPattern | - ContainsTypeScriptClassSyntaxExtension | - ContainsTypeScriptDecorator, - - ModuleScopeExcludes = - ContainsES6LetOrConst | - ContainsLexicalThis | - ContainsCapturedThis | - ContainsES6VariableBindingPattern | - ContainsES6ParameterBindingPattern, - - TypeExcludes = - ~ContainsTypeScript, - - CallOrArrayLiteralExcludes = - ContainsES6SpreadElement, - } - /* @internal */ export interface TransformResolver { getGeneratedNameForNode(node: Node): string; @@ -673,7 +499,7 @@ namespace ts { /** Pops the top node from the stack. */ popNode(): void; } - + // @factoryhidden("decorators", true) // @factoryhidden("modifiers", true) // @factoryhidden("parent", true) @@ -710,7 +536,7 @@ namespace ts { export interface ModifiersArray extends NodeArray { flags: number; } - + // @kind(SyntaxKind.AbstractKeyword, { create: false, update: false, test: false }) // @kind(SyntaxKind.AsyncKeyword, { create: false, update: false, test: false }) // @kind(SyntaxKind.ConstKeyword, { create: false, update: false, test: false }) @@ -722,7 +548,7 @@ namespace ts { // @kind(SyntaxKind.ProtectedKeyword, { create: false, update: false, test: false }) // @kind(SyntaxKind.StaticKeyword, { create: false, update: false, test: false }) export type Modifier = Node; - + // @kind(SyntaxKind.Identifier) export interface Identifier extends PrimaryExpression { // @factoryparam @@ -740,20 +566,22 @@ namespace ts { export type EntityName = Identifier | QualifiedName; + // @nodetest("isDeclarationNameNode") export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; - + export type PropertyName = Identifier | LiteralExpression | ComputedPropertyName; - + // @factoryhidden("decorators", false) // @factoryhidden("modifiers", false) export interface Declaration extends Node { _declarationBrand: any; name?: DeclarationName; } - + export interface DeclarationStatement extends Declaration, Statement { + name?: Identifier; } - + // @kind(SyntaxKind.ComputedPropertyName) export interface ComputedPropertyName extends Node { expression: Expression; @@ -781,7 +609,7 @@ namespace ts { parameters: NodeArray; type?: TypeNode; } - + // @kind(SyntaxKind.CallSignature) // @factoryhidden("name") // @factoryhidden("decorators") @@ -831,7 +659,7 @@ namespace ts { name: Identifier | BindingPattern; // Declared binding element name initializer?: Expression; // Optional initializer } - + // @kind(SyntaxKind.PropertySignature) // @factoryorder("decorators", "modifiers", "name", "questionToken", "type") export interface PropertySignature extends TypeElement { @@ -853,6 +681,7 @@ namespace ts { export interface ObjectLiteralElement extends Declaration { _objectLiteralBrandBrand: any; + name?: PropertyName; } // @kind(SyntaxKind.PropertyAssignment) @@ -892,7 +721,7 @@ namespace ts { type?: TypeNode; initializer?: Expression; } - + export interface PropertyLikeDeclaration extends Declaration { name: PropertyName; } @@ -900,12 +729,12 @@ namespace ts { export interface BindingPattern extends Node { elements: NodeArray; } - + // @kind(SyntaxKind.ObjectBindingPattern) export type ObjectBindingPattern = BindingPattern; - + // @kind(SyntaxKind.ArrayBindingPattern) - export type ArrayBindingPattern = BindingPattern; + export type ArrayBindingPattern = BindingPattern; /** * Several node kinds share function-like features such as a signature, @@ -923,7 +752,6 @@ namespace ts { // @factoryparam questionToken?: Node; - // @newlexicalenvironment() body?: Block | Expression; } @@ -932,9 +760,7 @@ namespace ts { // @factoryorder("decorators", "modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body") export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement { name?: Identifier; - - // @newlexicalenvironment() - body?: Block; + body?: FunctionBody; } // @kind(SyntaxKind.MethodSignature) @@ -960,11 +786,9 @@ namespace ts { // @factoryorder("decorators", "modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body") export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { name: PropertyName; - - // @newlexicalenvironment() - body?: Block; + body?: FunctionBody; } - + // @kind(SyntaxKind.Constructor) // @factoryhidden("asteriskToken") // @factoryhidden("questionToken") @@ -972,8 +796,7 @@ namespace ts { // @factoryhidden("name") // @factoryorder("decorators", "modifiers", "name", "parameters", "type", "body") export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { - // @newlexicalenvironment() - body?: Block; + body?: FunctionBody; } // For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. @@ -992,18 +815,16 @@ namespace ts { export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { _accessorDeclarationBrand: any; name: PropertyName; - - // @newlexicalenvironment() - body: Block; + body: FunctionBody; } - + // @kind(SyntaxKind.GetAccessor) // @factoryhidden("typeParameters") // @factoryhidden("questionToken") // @factoryhidden("asteriskToken") // @factoryorder("decorators", "modifiers", "name", "parameters", "type", "body") export type GetAccessorDeclaration = AccessorDeclaration; - + // @kind(SyntaxKind.SetAccessor) // @factoryhidden("typeParameters") // @factoryhidden("questionToken") @@ -1018,6 +839,7 @@ namespace ts { _indexSignatureDeclarationBrand: any; } + // @nodetest("isTypeNodeNode") export interface TypeNode extends Node { _typeNodeBrand: any; } @@ -1025,13 +847,13 @@ namespace ts { export interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration { _functionOrConstructorTypeNodeBrand: any; } - + // @kind(SyntaxKind.FunctionType) // @factoryhidden("name") // @factoryhidden("decorators") // @factoryhidden("modifiers") export type FunctionTypeNode = FunctionOrConstructorTypeNode; - + // @kind(SyntaxKind.ConstructorType) // @factoryhidden("name") // @factoryhidden("decorators") @@ -1054,7 +876,7 @@ namespace ts { export interface TypeQueryNode extends TypeNode { exprName: EntityName; } - + // A TypeLiteral is the declaration node for an anonymous symbol. // @kind(SyntaxKind.TypeLiteral) // @factoryhidden("name", true) @@ -1102,13 +924,19 @@ namespace ts { // takes an Expression without any error. By using the 'brands' we ensure that the type // checker actually thinks you have something of the right type. Note: the brands are // never actually given values. At runtime they have zero cost. - // @kind(SyntaxKind.OmittedExpression) // @nodetest("isExpressionNode") export interface Expression extends Node { _expressionBrand: any; contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution } + // @kind(SyntaxKind.OmittedExpression) + export type OmittedExpression = Expression; + + // @kind(SyntaxKind.RawExpression) + export interface RawExpression extends LiteralExpression { + } + export interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } @@ -1141,7 +969,7 @@ namespace ts { // @kind(SyntaxKind.TrueKeyword) // @kind(SyntaxKind.FalseKeyword) - // @kind(SyntaxKind.NullKeyword, { create: false }) + // @kind(SyntaxKind.NullKeyword) // @kind(SyntaxKind.ThisKeyword) // @kind(SyntaxKind.SuperKeyword) export interface PrimaryExpression extends MemberExpression { @@ -1167,7 +995,7 @@ namespace ts { export interface AwaitExpression extends UnaryExpression { expression: UnaryExpression; } - + // @kind(SyntaxKind.YieldExpression) export interface YieldExpression extends Expression { // @factoryparam @@ -1194,14 +1022,15 @@ namespace ts { whenFalse: Expression; } + export type FunctionBody = Block; + export type ConciseBody = FunctionBody | Expression; + // @kind(SyntaxKind.FunctionExpression) // @factoryhidden("questionToken", true) // @factoryorder("decorators", "modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body") export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration { name?: Identifier; - - // @newlexicalenvironment() - body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional + body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } // @kind(SyntaxKind.ArrowFunction) @@ -1214,6 +1043,7 @@ namespace ts { export interface ArrowFunction extends Expression, FunctionLikeDeclaration { // @factoryparam equalsGreaterThanToken: Node; + body: ConciseBody; } // The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral, @@ -1311,7 +1141,7 @@ namespace ts { expression: Expression; type: TypeNode; } - + // @kind(SyntaxKind.TypeAssertionExpression) export interface TypeAssertion extends UnaryExpression { type: TypeNode; @@ -1364,7 +1194,7 @@ namespace ts { // @kind(SyntaxKind.JsxExpression) export interface JsxExpression extends Expression { - expression?: Expression; + expression: Expression; } // @kind(SyntaxKind.JsxText) @@ -1378,10 +1208,16 @@ namespace ts { export interface Statement extends Node { _statementBrand: any; } - + + // @kind(SyntaxKind.RawStatement) + export interface RawStatement extends Statement { + // @factoryparam + text: string; + } + // @kind(SyntaxKind.EmptyStatement) export type EmptyStatement = Statement; - + // @kind(SyntaxKind.DebuggerStatement) export type DebuggerStatement = Statement; @@ -1391,6 +1227,8 @@ namespace ts { name?: Identifier; } + export type BlockLike = SourceFile | Block | ModuleBlock | CaseClause; + // @kind(SyntaxKind.Block) export interface Block extends Statement { statements: NodeArray; @@ -1452,10 +1290,10 @@ namespace ts { export interface BreakOrContinueStatement extends Statement { label?: Identifier; } - + // @kind(SyntaxKind.BreakStatement) export type BreakStatement = BreakOrContinueStatement; - + // @kind(SyntaxKind.ContinueStatement) export type ContinueStatement = BreakOrContinueStatement; @@ -1541,7 +1379,7 @@ namespace ts { _classElementBrand: any; name?: PropertyName; } - + export interface TypeElement extends Declaration { _typeElementBrand: any; name?: PropertyName; @@ -1587,12 +1425,12 @@ namespace ts { members: NodeArray; } + export type ModuleBody = ModuleBlock | ModuleDeclaration; + // @kind(SyntaxKind.ModuleDeclaration) export interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; - - // @newlexicalenvironment() - body: ModuleBlock | ModuleDeclaration; + body: ModuleBody; } // @kind(SyntaxKind.ModuleBlock) @@ -1660,7 +1498,7 @@ namespace ts { // @kind(SyntaxKind.NamedImports) export type NamedImports = NamedImportsOrExports; - + // @kind(SyntaxKind.NamedExports) export type NamedExports = NamedImportsOrExports; @@ -1673,7 +1511,7 @@ namespace ts { // @kind(SyntaxKind.ImportSpecifier) export type ImportSpecifier = ImportOrExportSpecifier; - + // @kind(SyntaxKind.ExportSpecifier) export type ExportSpecifier = ImportOrExportSpecifier; @@ -1764,7 +1602,7 @@ namespace ts { parameters: NodeArray; type: JSDocType; } - + // @kind(SyntaxKind.JSDocVariadicType) export interface JSDocVariadicType extends JSDocType { type: JSDocType; @@ -1825,6 +1663,11 @@ namespace ts { isBracketed: boolean; } + export interface AmdDependency { + path: string; + name: string; + } + // Source files are declarations when they are external modules. // @kind(SyntaxKind.SourceFile, { create: "createSourceFileNode", update: "updateSourceFileNode" }) // @factoryhidden("decorators") @@ -1834,16 +1677,23 @@ namespace ts { statements: NodeArray; endOfFileToken: Node; + // @factoryparam fileName: string; + // @factoryparam text: string; - amdDependencies: {path: string; name: string}[]; + // @factoryparam + amdDependencies: AmdDependency[]; + // @factoryparam moduleName: string; + // @factoryparam referencedFiles: FileReference[]; + // @factoryparam languageVariant: LanguageVariant; - + // this map is used by transpiler to supply alternative names for dependencies (i.e. in case of bundling) /* @internal */ + // @factoryparam renamedDependencies?: Map; /** @@ -1854,15 +1704,19 @@ namespace ts { * If any other file has this comment, it signals not to include lib.d.ts * because this containing file is intended to act as a default library. */ + // @factoryparam hasNoDefaultLib: boolean; + // @factoryparam languageVersion: ScriptTarget; // The first node that causes this file to be an external module - // @factoryhidden + // @factoryparam /* @internal */ externalModuleIndicator: Node; + // @factoryparam /* @internal */ isDefaultLib: boolean; + // @factoryparam /* @internal */ identifiers: Map; /* @internal */ nodeCount: number; /* @internal */ identifierCount: number; @@ -1870,19 +1724,25 @@ namespace ts { // File level diagnostics reported by the parser (includes diagnostics about /// references // as well as code diagnostics). + // @factoryparam /* @internal */ parseDiagnostics: Diagnostic[]; // File level diagnostics reported by the binder. + // @factoryparam /* @internal */ bindDiagnostics: Diagnostic[]; // Stores a line map for the file. // This field should never be used directly to obtain line map, use getLineMap function instead. + // @factoryparam /* @internal */ lineMap: number[]; + // @factoryparam /* @internal */ classifiableNames?: Map; // Stores a mapping 'external module reference text' -> 'resolved file name' | undefined // It is used to resolve module names in the checker. // Content of this fiels should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead + // @factoryparam /* @internal */ resolvedModules: Map; + // @factoryparam /* @internal */ imports: LiteralExpression[]; } @@ -1910,12 +1770,12 @@ namespace ts { } export interface Program extends ScriptReferenceHost { - + /** * Get a list of root file names that were passed to a 'createProgram' */ getRootFileNames(): string[] - + /** * Get a list of files in the program */ @@ -2196,7 +2056,7 @@ namespace ts { getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; } @@ -2333,16 +2193,17 @@ namespace ts { EmitParam = 0x00000020, // Emit __param helper for decorators EmitAwaiter = 0x00000040, // Emit __awaiter EmitGenerator = 0x00000080, // Emit __generator - SuperInstance = 0x00000100, // Instance 'super' reference - SuperStatic = 0x00000200, // Static 'super' reference - ContextChecked = 0x00000400, // Contextual types have been assigned - LexicalArguments = 0x00000800, - CaptureArguments = 0x00001000, // Lexical 'arguments' used in body (for async functions) + EmitExportStar = 0x00000100, // Emit __export + SuperInstance = 0x00000200, // Instance 'super' reference + SuperStatic = 0x00000400, // Static 'super' reference + ContextChecked = 0x00000800, // Contextual types have been assigned + LexicalArguments = 0x00001000, + CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions) // Values for enum members have been computed, and any errors have been reported for them. - EnumValuesComputed = 0x00002000, - BlockScopedBindingInLoop = 0x00004000, - LexicalModuleMergesWithClass= 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration. + EnumValuesComputed = 0x00004000, + BlockScopedBindingInLoop = 0x00008000, + LexicalModuleMergesWithClass= 0x00010000, // Instantiated lexical module declaration is merged with a previous class declaration. } /* @internal */ @@ -2612,12 +2473,12 @@ namespace ts { Error, Message, } - + export const enum ModuleResolutionKind { Classic = 1, NodeJs = 2 } - + export interface CompilerOptions { allowNonTsExtensions?: boolean; charset?: string; @@ -2874,31 +2735,31 @@ namespace ts { byteOrderMark = 0xFEFF, tab = 0x09, // \t verticalTab = 0x0B, // \v - } - + } + export interface ModuleResolutionHost { fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' - // to determine location of bundled typings for node module + // to determine location of bundled typings for node module readFile(fileName: string): string; } - + export interface ResolvedModule { resolvedFileName: string; /* * Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be proper external module: - * - be a .d.ts file + * - be a .d.ts file * - use top level imports\exports * - don't use tripleslash references */ isExternalLibraryImport?: boolean; } - + export interface ResolvedModuleWithFailedLookupLocations { resolvedModule: ResolvedModule; failedLookupLocations: string[]; } - + export interface CompilerHost extends ModuleResolutionHost { getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile; getCancellationToken?(): CancellationToken; @@ -2908,17 +2769,243 @@ namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - + /* - * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of - * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler + * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of + * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler * will appply built-in module resolution logic and use members of ModuleResolutionHost to ask host specific questions). - * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just - * 'throw new Error("NotImplemented")' + * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just + * 'throw new Error("NotImplemented")' */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; } + // @internal + export type Through = (node: TIn, write: (node: TOut) => void) => void; + + // Flags enum to track count of temp variables and a few dedicated names + // @internal + export const enum TempFlags { + Auto = 0x00000000, // No preferred name + CountMask = 0x0FFFFFFF, // Temp variable counter + _i = 0x10000000, // Use/preference flag for '_i' + } + + /* @internal */ + export const enum TransformFlags { + // + // Facts + // + + /** + * A fact that states that this node is TypeScript syntax. + */ + TypeScript = 1 << 0, + + /** + * A fact that states that the subtree of this node contains TypeScript syntax. + */ + ContainsTypeScript = 1 << 1, + + /** + * A fact that states that this node is Jsx syntax. + */ + Jsx = 1 << 2, + + /** + * A fact that states that the subtree of this node contains Jsx syntax. + */ + ContainsJsx = 1 << 3, + + /** + * A fact that states that this node is ES6 syntax. + */ + ES6 = 1 << 4, + + /** + * A fact that states that the subtree of this node contains ES6 syntax. + */ + ContainsES6 = 1 << 5, + + // + // Markers + // + + /** + * A marker used by a descendant node to indicate that one of its ancestors should be considered TypeScript syntax. + * @remarks + * This is used to force the TypeScript class transformation for classes that contain: + * - Property Initializers + * - Constructor Parameters with accessibility modifiers. + * - Decorators + */ + ContainerIsTypeScript = 1 << 16, + ContainerIsES6 = 1 << 17, + ContainsLexicalThis = 1 << 18, + ContainsCapturedLexicalThis = 1 << 19, + ContainsDefaultValueAssignments = 1 << 20, + + // ContainsES6Yield = 1 << 20, + // ContainsES6SpreadElement = 1 << 21, + // ContainsES6LetOrConst = 1 << 22, + // ContainsES6ComputedPropertyName = 1 << 23, + + // + // Assertions + // + + /** + * Asserts that this node is TypeScript syntax, and that it's ancestors contain TypeScript syntax. + */ + ThisNodeIsTypeScript = TypeScript | ContainsTypeScript, + + /** + * Asserts that this node is Jsx syntax, and that it's ancestors contain Jsx syntax. + */ + ThisNodeIsJsx = Jsx | ContainsJsx, + + /** + * Asserts that this node is ES6 syntax, and that it's ancestors contain ES6 syntax. + */ + ThisNodeIsES6 = ES6 | ContainsES6, + + // + // Queries + // + + // SubtreeContainsLexicalThis = + // ContainsLexicalThis, + + // SubtreeCapturesLexicalThis = + // ContainsCapturedThis, + + // SubtreeContainsRestParameter = + // ContainsES6RestParameter, + + // SubtreeContainsParameterBindingPattern = + // ContainsES6ParameterBindingPattern, + + // SubtreeContainsParameterInitializer = + // ContainsES6ParameterInitializer, + + // ThisParameterNeedsTransform = + // ContainsES6VariableBindingPattern | + // ContainsES6ParameterBindingPattern | + // ContainsES6RestParameter | + // ContainsES6ParameterInitializer, + + // SubtreeContainsES6ParameterOrCapturedThis = + // ContainsES6ParameterBindingPattern | + // ContainsES6ParameterInitializer | + // ContainsES6RestParameter | + // ContainsCapturedThis, + + // + // Scope Exclusions + // + + NodeExcludes = + TypeScript | + Jsx | + ES6, + + ArrowFunctionExcludes = + ContainerIsTypeScript | + ContainerIsES6 | + ContainsDefaultValueAssignments | + ContainsLexicalThis, + + FunctionDeclarationOrExpressionExcludes = + ContainerIsTypeScript | + ContainerIsES6 | + ContainsDefaultValueAssignments | + ContainsCapturedLexicalThis | + ContainsLexicalThis, + + ConstructorExcludes = + ContainsDefaultValueAssignments | + ContainsLexicalThis | + ContainsCapturedLexicalThis, + + MethodDeclarationExcludes = + ContainsDefaultValueAssignments | + ContainsLexicalThis | + ContainsCapturedLexicalThis, + + GetOrSetAccessorExcludes = + ContainsDefaultValueAssignments | + ContainsLexicalThis | + ContainsCapturedLexicalThis, + + ClassDeclarationOrExpressionExcludes = + ContainerIsTypeScript | + ContainsLexicalThis | + ContainsCapturedLexicalThis, + + ModuleScopeExcludes = + ContainerIsTypeScript | + ContainsLexicalThis | + ContainsCapturedLexicalThis, + + TypeExcludes = + ~ContainsTypeScript, + + // CallOrArrayLiteralExcludes = + // ContainsES6SpreadElement, + } + + // @internal + export interface NodeArrayWriter { + write(node: T): void; + } + + // @internal + export interface Transformer { + getEmitResolver(): EmitResolver; + getCompilerOptions(): CompilerOptions; + makeUniqueName(baseName: string): string; + getGeneratedNameForNode(node: Node): Identifier; + nodeHasGeneratedName(node: Node): boolean; + createUniqueIdentifier(baseName: string): Identifier; + createTempVariable(flags?: TempFlags): Identifier; + declareLocal(baseName?: string): Identifier; + hoistVariableDeclaration(name: Identifier): void; + hoistFunctionDeclaration(func: FunctionDeclaration): void; + createParentNavigator(): ParentNavigator; + getRootNode(): SourceFile; + getParentNode(): Node; + getCurrentNode(): Node; + tryPushNode(node: Node): boolean; + pushNode(node: Node): void; + popNode(): void; + findAncestorNode(match: (node: Node) => node is T): T; + findAncestorNode(match: (node: Node) => boolean): Node; + getDeclarationName(node: DeclarationStatement): Identifier; + getDeclarationName(node: ClassLikeDeclaration): Identifier; + getDeclarationName(node: Declaration): DeclarationName; + getClassMemberPrefix(node: ClassLikeDeclaration, member: ClassElement): LeftHandSideExpression; + + emitEmitHelpers(write: (node: Statement) => void): void; + emitExportStarHelper(write: (node: Statement) => void): void; + + startLexicalEnvironment(): void; + endLexicalEnvironment(out: ((node: Statement) => void) | Statement[]): void; + + pipeNode(node: TIn, through: (node: TIn, write: (node: TOut) => void) => void, out: ((node: TOut) => void) | TOut[]): void; + pipeNodes(node: TIn[], through: (node: TIn, write: (node: TOut) => void) => void, out: ((node: TOut) => void) | TOut[], start?: number, count?: number): void; + mapNode(node: TIn, through: (node: TIn, write: (node: TOut) => void) => void): TOut; + mapNodes(nodes: TIn[], through: (node: TIn, write: (node: TOut) => void) => void, start?: number, count?: number): TOut[]; + flattenNode(node: TIn, through: (node: TIn, write: (node: TOut) => void) => void): TOut[]; + visitNode(node: T, visitor: (node: Node, write: (node: Node) => void) => void, test: (node: Node) => node is T): T; + visitNodes(nodes: T[], visitor: (node: Node, write: (node: Node) => void) => void, test: (node: Node) => node is T, start?: number, count?: number): NodeArray; + visitStatement(node: Statement, visitor: (node: Node, write: (node: Node) => void) => void): Statement; + visitModuleBody(node: ModuleBody, visitor: (node: Node, write: (node: Node) => void) => void): ModuleBody; + visitFunctionBody(node: FunctionBody, visitor: (node: Node, write: (node: Node) => void) => void): FunctionBody; + visitConciseBody(node: ConciseBody, visitor: (node: Node, write: (node: Node) => void) => void): ConciseBody; + visitSourceFile(node: SourceFile, visitor: (node: Node, write: (node: Node) => void) => void): SourceFile; + accept(node: T, visitor: (node: Node, write: (node: Node) => void) => void): T; + } + export interface TextSpan { start: number; length: number; @@ -2947,7 +3034,7 @@ namespace ts { // operation caused diagnostics to be returned by storing and comparing the return value // of this method before/after the operation is performed. getModificationCount(): number; - + /* @internal */ reattachFileDiagnostics(newFile: SourceFile): void; } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f6cc6fd972f..1d2a45fb7c0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -97,8 +97,8 @@ namespace ts { } return true; - } - + } + export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean { return sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleNameText); } @@ -391,7 +391,7 @@ namespace ts { return flags; } - + export function isConst(navigable: ParentNavigable): boolean { return !!(getCombinedNodeFlags(navigable) & NodeFlags.Const); } @@ -400,7 +400,7 @@ namespace ts { return !!(getCombinedNodeFlags(navigable) & NodeFlags.Let); } - export function isPrologueDirective(node: Node): boolean { + export function isPrologueDirective(node: Statement): boolean { return node.kind === SyntaxKind.ExpressionStatement && (node).expression.kind === SyntaxKind.StringLiteral; } @@ -409,10 +409,10 @@ namespace ts { 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; @@ -680,7 +680,7 @@ namespace ts { return node; } } - + return undefined; } @@ -692,7 +692,7 @@ namespace ts { return node; } } - + return undefined; } @@ -774,7 +774,7 @@ namespace ts { break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. - if (isParameter(nav.getParent()) + if (isParameter(nav.getParent()) && isClassElement(nav.getGrandparent())) { // If the decorator's parent is a Parameter, we resolve the this container from // the grandparent class declaration. @@ -964,19 +964,19 @@ namespace ts { break; } } - + return nav.getKind() === SyntaxKind.TypeQuery; - + case SyntaxKind.Identifier: if (nav.getParent().kind === SyntaxKind.TypeQuery) { return true; } - + // fall through case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: nav.moveToParent(); - + let parent = nav.getNode(); switch (parent.kind) { case SyntaxKind.VariableDeclaration: @@ -1062,23 +1062,23 @@ namespace ts { return Comparison.GreaterThan; } } - + 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 + 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: @@ -1101,48 +1101,48 @@ namespace ts { 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: @@ -1150,28 +1150,28 @@ namespace ts { 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: @@ -1185,28 +1185,28 @@ namespace ts { 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 || @@ -1241,6 +1241,43 @@ namespace ts { } } + export function getLiteralText(node: LiteralExpression, sourceFile: SourceFile, languageVersion: ScriptTarget) { + // Any template literal or string literal with an extended escape + // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. + if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { + return getQuotedEscapedLiteralText("\"", node.text, "\""); + } + + // If we don't need to downlevel and we can reach the original source text using + // the node's parent reference, then simply get the text as it was originally written. + if (!nodeIsSynthesized(node) && node.parent) { + return getSourceTextOfNodeFromSourceFile(sourceFile, node); + } + + // If we can't reach the original source text, use the canonical form if it's a number, + // or an escaped quoted form of the original text if it's string-like. + switch (node.kind) { + case SyntaxKind.StringLiteral: + return getQuotedEscapedLiteralText("\"", node.text, "\""); + case SyntaxKind.NoSubstitutionTemplateLiteral: + return getQuotedEscapedLiteralText("`", node.text, "`"); + case SyntaxKind.TemplateHead: + return getQuotedEscapedLiteralText("`", node.text, "${"); + case SyntaxKind.TemplateMiddle: + return getQuotedEscapedLiteralText("}", node.text, "${"); + case SyntaxKind.TemplateTail: + return getQuotedEscapedLiteralText("}", node.text, "`"); + case SyntaxKind.NumericLiteral: + return node.text; + } + + Debug.fail(`Literal kind '${node.kind}' not accounted for.`); + } + + function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) { + return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote; + } + export function hasQuestionToken(node: Node) { if (node) { switch (node.kind) { @@ -1422,11 +1459,11 @@ 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): name is Identifier | StringLiteral | LiteralExpression { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { @@ -1503,11 +1540,11 @@ namespace ts { if (isBinaryExpression(node)) { if (node.operatorToken.kind === SyntaxKind.EqualsToken) { let left = node.left; - return left.kind === SyntaxKind.ObjectLiteralExpression + return left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression; } } - + return false; } @@ -1683,7 +1720,7 @@ namespace ts { export function nodeStartsNewLexicalEnvironment(n: Node): boolean { return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile; } - + export function cloneEntityName(node: EntityName): EntityName { if (node.kind === SyntaxKind.Identifier) { let clone = createNode(SyntaxKind.Identifier); @@ -1703,7 +1740,7 @@ namespace ts { export function nodeIsSynthesized(node: Node): boolean { return node && node.pos === -1; } - + export function positionIsSynthesized(pos: number): boolean { return pos === -1; } @@ -1737,12 +1774,12 @@ namespace ts { function getModificationCount() { return modificationCount; } - + function reattachFileDiagnostics(newFile: SourceFile): void { if (!hasProperty(fileDiagnostics, newFile.fileName)) { return; } - + for (let diagnostic of fileDiagnostics[newFile.fileName]) { diagnostic.file = newFile; } @@ -2010,7 +2047,7 @@ namespace ts { } return false; } - + export interface AllAccessorDeclarations { firstAccessor: AccessorDeclaration; secondAccessor: AccessorDeclaration; @@ -2249,7 +2286,7 @@ namespace ts { } /** - * Tests whether the node is an ExpressionWithTypeArguments node that is part of the `extends` + * Tests whether the node is an ExpressionWithTypeArguments node that is part of the `extends` * clause of a class. */ export function isExpressionWithTypeArgumentsInClassExtendsClause(navigable: ParentNavigable): boolean { diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index ab4fcf93902..27cb3574473 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.isPartOfExpression(node) || node.kind === ts.SyntaxKind.Identifier) { + if (ts.isExpression(node) || node.kind === ts.SyntaxKind.Identifier) { this.logTypeAndSymbol(node); } @@ -71,4 +71,4 @@ class TypeWriterWalker { symbol: symbolString }); } -} +}